Skip to main content

PluginManager

Struct PluginManager 

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

Coordinates plugin discovery, cached metadata, and dispatch settings.

This is the main host-side facade for plugin integration. A typical caller constructs one manager, points it at explicit roots plus optional config and cache roots, then asks it for one of three things:

If you are implementing the plugin executable itself rather than the host, start in crate::core::plugin instead of here.

Implementations§

Source§

impl PluginManager

Source

pub fn refresh(&self)

Clears both passive and dispatch discovery caches.

Call this after changing plugin search roots or the filesystem state they point at so later browse or dispatch calls rescan discovery inputs. This does not clear in-memory command preferences such as provider selections.

§Examples
use osp_cli::plugin::PluginManager;

let manager = PluginManager::new(Vec::new());
manager.refresh();

assert!(manager.list_plugins().is_empty());
Source§

impl PluginManager

Source

pub fn dispatch( &self, command: &str, args: &[String], context: &PluginDispatchContext, ) -> Result<ResponseV1, PluginDispatchError>

Runs a plugin command and returns its validated structured response.

command is the full command path resolved against the active plugin catalog. args are passed to the plugin after that command name. context carries runtime hints, optional environment overrides, and an optional one-shot provider override for this dispatch only.

§Errors

Returns PluginDispatchError when provider resolution fails, the plugin subprocess cannot be executed, the subprocess times out, the plugin exits non-zero, or the returned JSON is syntactically or semantically invalid.

§Examples
use osp_cli::plugin::{PluginDispatchContext, PluginDispatchError, PluginManager};

let err = PluginManager::new(Vec::new())
    .dispatch("shared", &[], &PluginDispatchContext::default())
    .unwrap_err();

assert!(matches!(err, PluginDispatchError::CommandNotFound { .. }));
Source

pub fn dispatch_passthrough( &self, command: &str, args: &[String], context: &PluginDispatchContext, ) -> Result<RawPluginOutput, PluginDispatchError>

Runs a plugin command and returns raw stdout, stderr, and exit status.

Unlike PluginManager::dispatch, this does not attempt to decode or validate plugin JSON output. Non-zero exit codes are returned in RawPluginOutput::status_code rather than surfaced as PluginDispatchError::NonZeroExit.

§Errors

Returns PluginDispatchError when provider resolution fails, the plugin subprocess cannot be executed, or the subprocess times out.

§Examples
use osp_cli::plugin::{PluginDispatchContext, PluginDispatchError, PluginManager};

let err = PluginManager::new(Vec::new())
    .dispatch_passthrough("shared", &[], &PluginDispatchContext::default())
    .unwrap_err();

assert!(matches!(err, PluginDispatchError::CommandNotFound { .. }));
Source§

impl PluginManager

Source

pub fn new(explicit_dirs: Vec<PathBuf>) -> Self

Creates a plugin manager with the provided explicit search roots.

§Examples
use osp_cli::plugin::PluginManager;
use std::path::PathBuf;

let manager = PluginManager::new(vec![PathBuf::from("/plugins")]);

assert_eq!(manager.explicit_dirs().len(), 1);
Source

pub fn explicit_dirs(&self) -> &[PathBuf]

Returns the explicit plugin search roots configured for this manager.

Source

pub fn with_roots( self, config_root: Option<PathBuf>, cache_root: Option<PathBuf>, ) -> Self

Sets config and cache roots used for user plugin discovery and describe cache files.

The config root feeds the per-user plugin directory lookup. The cache root feeds the on-disk describe cache. This does not make command provider selections persistent by itself; those remain manager-local in-memory state.

§Examples
use osp_cli::plugin::PluginManager;
use std::path::PathBuf;

let manager = PluginManager::new(Vec::new()).with_roots(
    Some(PathBuf::from("/config")),
    Some(PathBuf::from("/cache")),
);

assert_eq!(manager.config_root(), Some(PathBuf::from("/config").as_path()));
assert_eq!(manager.cache_root(), Some(PathBuf::from("/cache").as_path()));
Source

pub fn config_root(&self) -> Option<&Path>

Returns the configured config root used to resolve the user plugin directory.

Source

pub fn cache_root(&self) -> Option<&Path>

Returns the configured cache root used for the describe metadata cache.

Source

pub fn with_default_roots(self, allow_default_roots: bool) -> Self

Enables or disables fallback to platform config/cache roots when explicit roots are not configured.

The default is true. Disable this when the caller wants plugin discovery and describe-cache state to stay fully in-memory unless explicit roots are provided.

Source

pub fn default_roots_enabled(&self) -> bool

Returns whether platform config/cache root fallback is enabled.

Source

pub fn with_process_timeout(self, timeout: Duration) -> Self

Sets the subprocess timeout used for plugin describe and dispatch calls.

Timeout values are clamped to at least one millisecond so the manager never stores a zero-duration subprocess timeout.

§Examples
use osp_cli::plugin::PluginManager;
use std::time::Duration;

let manager = PluginManager::new(Vec::new())
    .with_process_timeout(Duration::from_millis(0));

assert_eq!(manager.process_timeout(), Duration::from_millis(1));
Source

pub fn process_timeout(&self) -> Duration

Returns the subprocess timeout used for describe and dispatch calls.

Source

pub fn with_path_discovery(self, allow_path_discovery: bool) -> Self

Enables or disables fallback discovery through the process PATH.

PATH discovery is passive on browse/read surfaces. A PATH-discovered plugin will not be executed for --describe during passive listing or catalog building, so command metadata is unavailable there until the first command dispatch to that plugin. Dispatching a command triggers --describe as a cache miss and writes the result to the on-disk describe cache; subsequent browse and catalog calls will then see the full command metadata.

§Examples
use osp_cli::plugin::PluginManager;

let manager = PluginManager::new(Vec::new()).with_path_discovery(true);

assert!(manager.path_discovery_enabled());
Source

pub fn path_discovery_enabled(&self) -> bool

Returns whether fallback discovery through the process PATH is enabled.

Source

pub fn list_plugins(&self) -> Vec<PluginSummary>

Lists discovered plugins with health, command, and enablement status.

When PATH discovery is enabled, PATH-discovered plugins can appear here before their command metadata is available because passive discovery does not execute them for --describe.

§Examples
use osp_cli::plugin::PluginManager;

let plugins = PluginManager::new(Vec::new()).list_plugins();

assert!(plugins.is_empty());
Source

pub fn command_catalog(&self) -> Vec<CommandCatalogEntry>

Builds the effective command catalog after provider resolution and health filtering.

This is the host-facing “what commands exist?” view used by help, completion, and similar browse/read surfaces. PATH-discovered plugins only contribute commands here after describe metadata has been cached; passive discovery alone is not enough.

§Examples
use osp_cli::plugin::PluginManager;

let catalog = PluginManager::new(Vec::new()).command_catalog();

assert!(catalog.is_empty());
Source

pub fn command_policy_registry(&self) -> CommandPolicyRegistry

Builds a command policy registry from active plugin describe metadata.

Use this when plugin auth hints need to participate in the same runtime visibility and access evaluation as native commands. Commands that still require provider selection are omitted until one provider is selected explicitly.

§Examples
use osp_cli::plugin::PluginManager;

let registry = PluginManager::new(Vec::new()).command_policy_registry();

assert!(registry.is_empty());
Source

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

Returns completion words derived from the current plugin command catalog.

The returned list always includes the REPL backbone words used by the plugin/completion surface, even when no plugins are currently available.

§Examples
use osp_cli::plugin::PluginManager;

let words = PluginManager::new(Vec::new()).completion_words();

assert!(words.contains(&"help".to_string()));
assert!(words.contains(&"|".to_string()));
Source

pub fn repl_help_text(&self) -> String

Renders a plain-text help view for plugin commands in the REPL.

§Examples
use osp_cli::plugin::PluginManager;

let help = PluginManager::new(Vec::new()).repl_help_text();

assert!(help.contains("Backbone commands: help, exit, quit"));
assert!(help.contains("No plugin commands available."));
Source

pub fn command_providers(&self, command: &str) -> Vec<String>

Returns the available provider labels for a command after health and enablement filtering.

Unknown commands and commands with no currently available providers return an empty list.

§Examples
use osp_cli::plugin::PluginManager;

let providers = PluginManager::new(Vec::new()).command_providers("shared");

assert!(providers.is_empty());
Source

pub fn selected_provider_label(&self, command: &str) -> Option<String>

Returns the selected provider label when command resolution is unambiguous.

Returns None when the command is unknown, ambiguous, or currently unavailable after health and enablement filtering.

§Examples
use osp_cli::plugin::PluginManager;

let provider = PluginManager::new(Vec::new()).selected_provider_label("shared");

assert_eq!(provider, None);
Source

pub fn doctor(&self) -> DoctorReport

Produces a doctor report with plugin health summaries and command conflicts.

§Examples
use osp_cli::plugin::PluginManager;

let report = PluginManager::new(Vec::new()).doctor();

assert!(report.plugins.is_empty());
assert!(report.conflicts.is_empty());
Source

pub fn select_provider(&self, command: &str, plugin_id: &str) -> Result<()>

Applies an explicit provider selection for a command on this manager.

The selection is kept in the manager’s in-memory command-preference state and affects subsequent command resolution through this PluginManager value. It is not written to disk.

§Examples
use osp_cli::plugin::PluginManager;
let manager = PluginManager::new(vec![plugins_dir]);

assert_eq!(manager.selected_provider_label("shared"), None);

manager.select_provider("shared", "beta")?;

assert_eq!(
    manager.selected_provider_label("shared").as_deref(),
    Some("beta (explicit)")
);
§Errors

Returns an error when command or plugin_id is blank, when no currently available provider exports command, or when plugin_id is not one of the currently available providers for command.

Source

pub fn clear_provider_selection(&self, command: &str) -> Result<bool>

Clears any explicit in-memory provider selection for a command.

§Examples
use osp_cli::plugin::PluginManager;

let removed = PluginManager::new(Vec::new())
    .clear_provider_selection("shared")
    .unwrap();

assert!(!removed);
§Errors

Returns an error when command is blank.

Source

pub fn validate_provider_selection( &self, command: &str, plugin_id: &str, ) -> Result<()>

Verifies that a plugin is a currently available provider candidate for a command.

This validates the command/plugin pair against the manager’s current discovery view but does not change selection state or persist anything.

§Examples
use osp_cli::plugin::PluginManager;

let err = PluginManager::new(Vec::new())
    .validate_provider_selection("shared", "alpha")
    .unwrap_err();

assert!(err.to_string().contains("no available plugin provides command"));
§Errors

Returns an error when no currently available provider exports command, or when plugin_id is not one of the currently available providers for command.

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> AsAny for T
where T: Any,

Source§

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

Returns a reference to the value as Any
Source§

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

Returns a mutable reference to the value as Any
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<T> Downcast for T
where T: Any,

Source§

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

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

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

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

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

Source§

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.

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<D> OwoColorize for D

Source§

fn fg<C>(&self) -> FgColorDisplay<'_, C, Self>
where C: Color,

Set the foreground color generically Read more
Source§

fn bg<C>(&self) -> BgColorDisplay<'_, C, Self>
where C: Color,

Set the background color generically. Read more
Source§

fn black(&self) -> FgColorDisplay<'_, Black, Self>

Change the foreground color to black
Source§

fn on_black(&self) -> BgColorDisplay<'_, Black, Self>

Change the background color to black
Source§

fn red(&self) -> FgColorDisplay<'_, Red, Self>

Change the foreground color to red
Source§

fn on_red(&self) -> BgColorDisplay<'_, Red, Self>

Change the background color to red
Source§

fn green(&self) -> FgColorDisplay<'_, Green, Self>

Change the foreground color to green
Source§

fn on_green(&self) -> BgColorDisplay<'_, Green, Self>

Change the background color to green
Source§

fn yellow(&self) -> FgColorDisplay<'_, Yellow, Self>

Change the foreground color to yellow
Source§

fn on_yellow(&self) -> BgColorDisplay<'_, Yellow, Self>

Change the background color to yellow
Source§

fn blue(&self) -> FgColorDisplay<'_, Blue, Self>

Change the foreground color to blue
Source§

fn on_blue(&self) -> BgColorDisplay<'_, Blue, Self>

Change the background color to blue
Source§

fn magenta(&self) -> FgColorDisplay<'_, Magenta, Self>

Change the foreground color to magenta
Source§

fn on_magenta(&self) -> BgColorDisplay<'_, Magenta, Self>

Change the background color to magenta
Source§

fn purple(&self) -> FgColorDisplay<'_, Magenta, Self>

Change the foreground color to purple
Source§

fn on_purple(&self) -> BgColorDisplay<'_, Magenta, Self>

Change the background color to purple
Source§

fn cyan(&self) -> FgColorDisplay<'_, Cyan, Self>

Change the foreground color to cyan
Source§

fn on_cyan(&self) -> BgColorDisplay<'_, Cyan, Self>

Change the background color to cyan
Source§

fn white(&self) -> FgColorDisplay<'_, White, Self>

Change the foreground color to white
Source§

fn on_white(&self) -> BgColorDisplay<'_, White, Self>

Change the background color to white
Source§

fn default_color(&self) -> FgColorDisplay<'_, Default, Self>

Change the foreground color to the terminal default
Source§

fn on_default_color(&self) -> BgColorDisplay<'_, Default, Self>

Change the background color to the terminal default
Source§

fn bright_black(&self) -> FgColorDisplay<'_, BrightBlack, Self>

Change the foreground color to bright black
Source§

fn on_bright_black(&self) -> BgColorDisplay<'_, BrightBlack, Self>

Change the background color to bright black
Source§

fn bright_red(&self) -> FgColorDisplay<'_, BrightRed, Self>

Change the foreground color to bright red
Source§

fn on_bright_red(&self) -> BgColorDisplay<'_, BrightRed, Self>

Change the background color to bright red
Source§

fn bright_green(&self) -> FgColorDisplay<'_, BrightGreen, Self>

Change the foreground color to bright green
Source§

fn on_bright_green(&self) -> BgColorDisplay<'_, BrightGreen, Self>

Change the background color to bright green
Source§

fn bright_yellow(&self) -> FgColorDisplay<'_, BrightYellow, Self>

Change the foreground color to bright yellow
Source§

fn on_bright_yellow(&self) -> BgColorDisplay<'_, BrightYellow, Self>

Change the background color to bright yellow
Source§

fn bright_blue(&self) -> FgColorDisplay<'_, BrightBlue, Self>

Change the foreground color to bright blue
Source§

fn on_bright_blue(&self) -> BgColorDisplay<'_, BrightBlue, Self>

Change the background color to bright blue
Source§

fn bright_magenta(&self) -> FgColorDisplay<'_, BrightMagenta, Self>

Change the foreground color to bright magenta
Source§

fn on_bright_magenta(&self) -> BgColorDisplay<'_, BrightMagenta, Self>

Change the background color to bright magenta
Source§

fn bright_purple(&self) -> FgColorDisplay<'_, BrightMagenta, Self>

Change the foreground color to bright purple
Source§

fn on_bright_purple(&self) -> BgColorDisplay<'_, BrightMagenta, Self>

Change the background color to bright purple
Source§

fn bright_cyan(&self) -> FgColorDisplay<'_, BrightCyan, Self>

Change the foreground color to bright cyan
Source§

fn on_bright_cyan(&self) -> BgColorDisplay<'_, BrightCyan, Self>

Change the background color to bright cyan
Source§

fn bright_white(&self) -> FgColorDisplay<'_, BrightWhite, Self>

Change the foreground color to bright white
Source§

fn on_bright_white(&self) -> BgColorDisplay<'_, BrightWhite, Self>

Change the background color to bright white
Source§

fn bold(&self) -> BoldDisplay<'_, Self>

Make the text bold
Source§

fn dimmed(&self) -> DimDisplay<'_, Self>

Make the text dim
Source§

fn italic(&self) -> ItalicDisplay<'_, Self>

Make the text italicized
Source§

fn underline(&self) -> UnderlineDisplay<'_, Self>

Make the text underlined
Make the text blink
Make the text blink (but fast!)
Source§

fn reversed(&self) -> ReversedDisplay<'_, Self>

Swap the foreground and background colors
Source§

fn hidden(&self) -> HiddenDisplay<'_, Self>

Hide the text
Source§

fn strikethrough(&self) -> StrikeThroughDisplay<'_, Self>

Cross out the text
Source§

fn color<Color>(&self, color: Color) -> FgDynColorDisplay<'_, Color, Self>
where Color: DynColor,

Set the foreground color at runtime. Only use if you do not know which color will be used at compile-time. If the color is constant, use either OwoColorize::fg or a color-specific method, such as OwoColorize::green, Read more
Source§

fn on_color<Color>(&self, color: Color) -> BgDynColorDisplay<'_, Color, Self>
where Color: DynColor,

Set the background color at runtime. Only use if you do not know what color to use at compile-time. If the color is constant, use either OwoColorize::bg or a color-specific method, such as OwoColorize::on_yellow, Read more
Source§

fn fg_rgb<const R: u8, const G: u8, const B: u8>( &self, ) -> FgColorDisplay<'_, CustomColor<R, G, B>, Self>

Set the foreground color to a specific RGB value.
Source§

fn bg_rgb<const R: u8, const G: u8, const B: u8>( &self, ) -> BgColorDisplay<'_, CustomColor<R, G, B>, Self>

Set the background color to a specific RGB value.
Source§

fn truecolor(&self, r: u8, g: u8, b: u8) -> FgDynColorDisplay<'_, Rgb, Self>

Sets the foreground color to an RGB value.
Source§

fn on_truecolor(&self, r: u8, g: u8, b: u8) -> BgDynColorDisplay<'_, Rgb, Self>

Sets the background color to an RGB value.
Source§

fn style(&self, style: Style) -> Styled<&Self>

Apply a runtime-determined style
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> QuoteExt for T
where T: ?Sized,

Source§

fn push_quoted<'q, Q, S>(&mut self, _q: Q, s: S)
where Q: QuoteInto<T>, S: Into<Quotable<'q>>,

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