spec_ai_plugin/lib.rs
1//! Plugin system for custom tools in spec-ai
2//!
3//! This crate provides the infrastructure for loading and running custom tools
4//! implemented as dynamic libraries (`.dylib` on macOS, `.so` on Linux, `.dll` on Windows).
5//!
6//! # For Plugin Authors
7//!
8//! To create a plugin, add this crate as a dependency with the `plugin-api` feature:
9//!
10//! ```toml
11//! [dependencies]
12//! spec-ai-plugin = { version = "0.4", features = ["plugin-api"] }
13//! ```
14//!
15//! Then implement your tools using the ABI-stable types:
16//!
17//! ```rust,ignore
18//! use abi_stable::std_types::{RStr, RString, RVec};
19//! use spec_ai_plugin::abi::{
20//! PluginModule, PluginModuleRef, PluginTool, PluginToolInfo,
21//! PluginToolRef, PluginToolResult, PLUGIN_API_VERSION,
22//! };
23//!
24//! // Define your tool
25//! extern "C" fn my_tool_info() -> PluginToolInfo {
26//! PluginToolInfo::new(
27//! "my_tool",
28//! "Description of my tool",
29//! r#"{"type": "object", "properties": {}}"#,
30//! )
31//! }
32//!
33//! extern "C" fn my_tool_execute(args_json: RStr<'_>) -> PluginToolResult {
34//! PluginToolResult::success("Tool executed successfully")
35//! }
36//!
37//! static MY_TOOL: PluginTool = PluginTool {
38//! info: my_tool_info,
39//! execute: my_tool_execute,
40//! initialize: None,
41//! };
42//!
43//! // Export the plugin module
44//! extern "C" fn api_version() -> u32 { PLUGIN_API_VERSION }
45//! extern "C" fn plugin_name() -> RString { RString::from("my-plugin") }
46//! extern "C" fn get_tools() -> RVec<PluginToolRef> {
47//! RVec::from(vec![&MY_TOOL])
48//! }
49//!
50//! #[abi_stable::export_root_module]
51//! fn get_library() -> PluginModuleRef {
52//! PluginModuleRef::from_prefix(PluginModule {
53//! api_version,
54//! plugin_name,
55//! get_tools,
56//! shutdown: None,
57//! })
58//! }
59//! ```
60//!
61//! # For Host Applications
62//!
63//! Use the [`loader::PluginLoader`] to discover and load plugins from a directory:
64//!
65//! ```rust,ignore
66//! use spec_ai_plugin::loader::{PluginLoader, expand_tilde};
67//! use std::path::Path;
68//!
69//! let mut loader = PluginLoader::new();
70//! let stats = loader.load_directory(&expand_tilde(Path::new("~/.spec-ai/tools")))?;
71//!
72//! println!("Loaded {} plugins with {} tools", stats.loaded, stats.tools_loaded);
73//!
74//! for (tool, plugin_name) in loader.all_tools() {
75//! let info = (tool.info)();
76//! println!(" - {} from {}", info.name, plugin_name);
77//! }
78//! ```
79
80pub mod abi;
81pub mod error;
82pub mod loader;
83
84// Re-export commonly used types
85pub use abi::{
86 PluginModule, PluginModuleRef, PluginTool, PluginToolInfo, PluginToolRef, PluginToolResult,
87 PLUGIN_API_VERSION,
88};
89pub use error::PluginError;
90pub use loader::{expand_tilde, LoadStats, LoadedPlugin, PluginLoader};