pub struct SkillStore { /* private fields */ }Expand description
Persistent storage for skills with in-memory caching.
Manages a collection of skills loaded from Markdown files on disk.
Uses a RwLock<HashMap> for thread-safe concurrent access.
§Thread Safety
All operations use async/await with RwLock to allow multiple readers
or a single writer, ensuring safe concurrent access from multiple tasks.
§Example
let store = SkillStore::new(SkillStoreConfig::default());
store.initialize().await?;
// Get a specific skill
let skill = store.get_skill("my-skill").await?;
println!("Skill: {}", skill.name);Implementations§
Source§impl SkillStore
impl SkillStore
Sourcepub fn new(config: SkillStoreConfig) -> Self
pub fn new(config: SkillStoreConfig) -> Self
Create a new skill store with the given configuration.
The store is created empty and must be initialized using initialize
before it can be used.
§Arguments
config- Configuration specifying the skills directory path.
§Example
use bamboo_agent::skill::{SkillStore, SkillStoreConfig};
use std::path::PathBuf;
let config = SkillStoreConfig {
skills_dir: PathBuf::from("./skills"),
};
let store = SkillStore::new(config);Sourcepub async fn initialize(&self) -> SkillResult<()>
pub async fn initialize(&self) -> SkillResult<()>
Initialize the store, loading skills from disk.
This method performs the following steps:
- Creates the skills directory if it doesn’t exist.
- Attempts to load existing skills from disk.
- Creates built-in skills if no existing skills are found.
- Reloads skills into memory after initialization.
§Returns
Ok(()) on successful initialization.
§Errors
Returns SkillError if:
- The skills directory cannot be created.
- Skill files cannot be read or parsed.
- Built-in skills cannot be written.
§Example
let store = SkillStore::new(SkillStoreConfig::default());
store.initialize().await.expect("Failed to initialize");Sourcepub async fn reload(&self) -> SkillResult<usize>
pub async fn reload(&self) -> SkillResult<usize>
Reload skills from disk into the in-memory cache.
This is useful when skills have been modified on disk and you want to pick up the changes without restarting the application.
§Returns
The number of skills loaded.
§Example
// After editing a skill file externally
let count = store.reload().await?;
println!("Loaded {} skills", count);Sourcepub async fn list_skills(
&self,
filter: Option<SkillFilter>,
refresh: bool,
) -> Vec<SkillDefinition>
pub async fn list_skills( &self, filter: Option<SkillFilter>, refresh: bool, ) -> Vec<SkillDefinition>
List all skills with optional filtering.
Returns a sorted list of skills matching the specified filter criteria. Optionally refreshes the cache from disk before listing.
§Arguments
filter- Optional filter criteria (by category, tags, visibility, etc.).refresh- If true, reload skills from disk before listing.
§Returns
A vector of matching skills, sorted alphabetically by name.
§Example
// List all public skills, refreshing from disk
let filter = SkillFilter {
visibility: Some(SkillVisibility::Public),
..Default::default()
};
let skills = store.list_skills(Some(filter), true).await;Sourcepub async fn get_skill(&self, id: &str) -> SkillResult<SkillDefinition>
pub async fn get_skill(&self, id: &str) -> SkillResult<SkillDefinition>
Get a single skill by its ID.
Retrieves a skill from the in-memory cache by its unique identifier.
§Arguments
id- The skill ID (e.g., “skill-creator”).
§Returns
The matching SkillDefinition if found.
§Errors
Returns SkillError::NotFound if no skill matches the given ID.
§Example
let skill = store.get_skill("my-skill").await?;
println!("Description: {}", skill.description);Sourcepub async fn create_skill(
&self,
_skill: SkillDefinition,
) -> SkillResult<SkillDefinition>
pub async fn create_skill( &self, _skill: SkillDefinition, ) -> SkillResult<SkillDefinition>
Create a new skill (not supported - read-only mode).
Skills must be created by writing Markdown files directly to the skills directory. This method always returns an error.
§Errors
Always returns SkillError::ReadOnly.
Sourcepub async fn update_skill(
&self,
_id: &str,
_updates: SkillUpdate,
) -> SkillResult<SkillDefinition>
pub async fn update_skill( &self, _id: &str, _updates: SkillUpdate, ) -> SkillResult<SkillDefinition>
Update an existing skill (not supported - read-only mode).
Skills must be edited by modifying Markdown files directly. This method always returns an error.
§Errors
Always returns SkillError::ReadOnly.
Sourcepub async fn delete_skill(&self, _id: &str) -> SkillResult<()>
pub async fn delete_skill(&self, _id: &str) -> SkillResult<()>
Delete a skill (not supported - read-only mode).
Skills must be deleted by removing their Markdown files directly. This method always returns an error.
§Errors
Always returns SkillError::ReadOnly.
Sourcepub async fn enable_skill_global(&self, _id: &str) -> SkillResult<()>
pub async fn enable_skill_global(&self, _id: &str) -> SkillResult<()>
Enable a skill globally (not supported - read-only mode).
Skill visibility must be configured in the Markdown file’s frontmatter. This method always returns an error.
§Errors
Always returns SkillError::ReadOnly.
Sourcepub async fn disable_skill_global(&self, _id: &str) -> SkillResult<()>
pub async fn disable_skill_global(&self, _id: &str) -> SkillResult<()>
Disable a skill globally (not supported - read-only mode).
Skill visibility must be configured in the Markdown file’s frontmatter. This method always returns an error.
§Errors
Always returns SkillError::ReadOnly.
Sourcepub async fn enable_skill_for_chat(
&self,
_skill_id: &str,
_chat_id: &str,
) -> SkillResult<()>
pub async fn enable_skill_for_chat( &self, _skill_id: &str, _chat_id: &str, ) -> SkillResult<()>
Enable a skill for a specific chat (not supported - read-only mode).
Skill chat associations are managed externally, not through this API. This method always returns an error.
§Errors
Always returns SkillError::ReadOnly.
Sourcepub async fn disable_skill_for_chat(
&self,
_skill_id: &str,
_chat_id: &str,
) -> SkillResult<()>
pub async fn disable_skill_for_chat( &self, _skill_id: &str, _chat_id: &str, ) -> SkillResult<()>
Disable a skill for a specific chat (not supported - read-only mode).
Skill chat associations are managed externally, not through this API. This method always returns an error.
§Errors
Always returns SkillError::ReadOnly.
Sourcepub async fn get_all_skills(&self) -> Vec<SkillDefinition>
pub async fn get_all_skills(&self) -> Vec<SkillDefinition>
Get all skills from the cache.
Returns all loaded skills, sorted alphabetically by name.
This is a convenience method equivalent to list_skills(None, false).
§Returns
A vector of all skills in the store.
§Example
let skills = store.get_all_skills().await;
println!("Total skills: {}", skills.len());Sourcepub fn skills_dir(&self) -> &PathBuf
pub fn skills_dir(&self) -> &PathBuf
Get the path to the skills directory.
Returns the configured directory where skill Markdown files are stored.
§Returns
Reference to the skills directory path.
Sourcepub async fn get_categories(&self) -> Vec<String>
pub async fn get_categories(&self) -> Vec<String>
Get all unique categories across all skills.
Scans all loaded skills and extracts their category values, returning a deduplicated and sorted list.
§Returns
A sorted vector of unique category names.
§Example
let categories = store.get_categories().await;
for category in categories {
println!("Category: {}", category);
}Sourcepub async fn export_to_markdown(
&self,
skill_ids: Option<Vec<String>>,
) -> SkillResult<String>
pub async fn export_to_markdown( &self, skill_ids: Option<Vec<String>>, ) -> SkillResult<String>
Export skills to Markdown format.
Renders one or more skills as Markdown documents with YAML frontmatter. Useful for creating backups or sharing skills.
§Arguments
skill_ids- Optional list of skill IDs to export. IfNone, exports all skills.
§Returns
A Markdown string containing all exported skills, separated by blank lines.
§Errors
Returns SkillError if Markdown rendering fails.
§Example
// Export specific skills
let markdown = store.export_to_markdown(
Some(vec!["skill-creator".to_string()])
).await?;
println!("{}", markdown);
// Export all skills
let all_markdown = store.export_to_markdown(None).await?;