pub mod loader;
pub mod manager;
pub use loader::{PluginApiError, PluginLoader, PluginRegistrarApi, PLUGIN_ABI_VERSION};
pub use manager::PluginManager;
use crate::config::Config;
use crate::network::delivery::{DeliveryOptions, DeliveryOutcome, DeliveryRuntime};
use crate::network::message::Message;
use crate::events::dispatcher::EventHandle;
use crate::network::peer_manager::PeerManager;
use crate::network::PeerStore;
use std::sync::Arc;
use tokio::sync::RwLock;
#[derive(Clone)]
pub struct PluginContext {
pub peer_manager: Arc<PeerManager>,
pub peer_store: PeerStore,
pub events: EventHandle,
pub local_node_id: String,
pub config: Config,
pub allow_console: bool,
plugin_manager: Arc<RwLock<Option<Arc<PluginManager>>>>,
}
impl PluginContext {
pub fn new(
peer_manager: Arc<PeerManager>,
peer_store: PeerStore,
events: EventHandle,
local_node_id: String,
config: Config,
allow_console: bool,
) -> Self {
Self {
peer_manager,
peer_store,
events,
local_node_id,
config,
allow_console,
plugin_manager: Arc::new(RwLock::new(None)),
}
}
pub async fn set_plugin_manager(&self, plugin_manager: Arc<PluginManager>) {
*self.plugin_manager.write().await = Some(plugin_manager);
}
pub async fn deliver_message(
&self,
message: Message,
options: DeliveryOptions,
) -> DeliveryOutcome {
let plugin_manager = self.plugin_manager.read().await.clone();
let Some(plugin_manager) = plugin_manager else {
return DeliveryOutcome::DeliveryFailed {
reason: crate::network::delivery::DeliveryFailureReason::PolicyDenied,
};
};
DeliveryRuntime::new(
(*self.peer_manager).clone(),
plugin_manager,
self.config.clone(),
self.local_node_id.clone(),
Some(self.peer_store.clone()),
self.allow_console,
)
.deliver_message(message, options)
.await
}
pub async fn send_message(
&self,
to: &str,
message: Message,
options: DeliveryOptions,
) -> DeliveryOutcome {
let mut outbound = message;
outbound.from = self.local_node_id.clone();
outbound.to = to.to_string();
self.deliver_message(outbound, options).await
}
}
#[async_trait::async_trait]
pub trait Plugin: Send + Sync {
async fn on_message(&self, message: &Message, ctx: &PluginContext);
fn subscribed_extension_kinds(&self) -> Option<&[&str]> {
None
}
async fn on_prompt(&self, _input: &str, _ctx: &PluginContext) -> Option<String> {
None
}
fn prompt_prefix(&self) -> Option<&str> {
None
}
fn early_config_defaults(&self) -> Option<crate::config::ConfigDefaults> {
None
}
}
pub trait PluginRegistrar {
fn register_handler(&mut self, plugin: Box<dyn Plugin>);
}