Skip to main content

fastskill_core/
lib.rs

1//! # FastSkill Service Layer (Rust Implementation)
2//!
3//! This crate provides a high-performance, memory-safe implementation of the FastSkill
4//! service layer. It serves as the reference implementation for other language
5//! bindings and can be used standalone or as a library.
6//!
7//! ## Architecture
8//!
9//! The service layer provides:
10//! - Skill management (CRUD operations)
11//! - Metadata and discovery services
12//! - Progressive loading of skill content
13//! - Tool calling and script execution
14//! - Hot reloading capabilities
15//! - Security sandboxing
16//!
17//! ## Example Usage
18//!
19//! ```rust,no_run
20//! use fastskill_core::{FastSkillService, ServiceConfig};
21//! use std::path::PathBuf;
22//!
23//! #[tokio::main]
24//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
25//!     let config = ServiceConfig {
26//!         skill_storage_path: PathBuf::from("./skills"),
27//!         ..Default::default()
28//!     };
29//!
30//!     let service = FastSkillService::new(config).await?;
31//!
32//!     // List available skills
33//!     let skills = service.skill_manager().list_skills(None).await?;
34//!     println!("Found {} skills", skills.len());
35//!
36//!     // Discover relevant skills
37//!     let relevant_skills = service.metadata_service()
38//!         .discover_skills("extract text from PDF")
39//!         .await?;
40//!
41//!     println!("Found {} relevant skills", relevant_skills.len());
42//!
43//!     // Get available tools
44//!     let tools = service.tool_service().get_available_tools().await?;
45//!     println!("Available tools: {:?}", tools);
46//!
47//!     Ok(())
48//! }
49//! ```
50
51pub mod core;
52pub mod events;
53pub mod execution;
54pub mod http;
55pub mod output;
56pub mod search;
57pub mod security;
58pub mod storage;
59pub mod validation;
60
61pub use core::context_resolver::{
62    ContentMode, ContextResolver, ResolveContextRequest, ResolveContextResponse, ResolveScope,
63    ResolvedSkill,
64};
65pub use core::embedding::{EmbeddingService, OpenAIEmbeddingService};
66pub use core::loading::{LoadedSkill, ProgressiveLoadingService};
67pub use core::manifest::SkillProjectToml;
68pub use core::metadata::{
69    parse_yaml_frontmatter, MetadataService, SkillFrontmatter, SkillMetadata,
70};
71pub use core::routing::{RoutedSkill, RoutingService};
72pub use core::service::SkillId;
73pub use core::service::{EmbeddingConfig, FastSkillService, ServiceConfig, ServiceError};
74pub use core::skill_manager::{SkillDefinition, SkillManagementService};
75pub use core::tool_calling::{AvailableTool, ToolCallingService, ToolResult};
76pub use core::vector_index::{
77    IndexedSkill, SkillMatch, VectorIndexService, VectorIndexServiceImpl,
78};
79
80// Re-export search and output types
81pub use output::OutputFormat;
82pub use search::{execute, SearchError, SearchQuery, SearchResultItem, SearchScope};
83
84// Re-export commonly used types
85pub use async_trait::async_trait;
86pub use serde::{Deserialize, Serialize};
87pub use std::collections::HashMap;
88pub use std::path::{Path, PathBuf};
89pub use std::sync::Arc;
90pub use tokio::sync::{Mutex, RwLock};
91
92/// Version of the service layer
93pub const VERSION: &str = env!("CARGO_PKG_VERSION");
94
95/// Initialize logging for the service layer (safe for testing)
96pub fn init_logging() {
97    init_logging_with_verbose(false)
98}
99
100/// Initialize logging for the service layer with optional verbose mode
101pub fn init_logging_with_verbose(verbose: bool) {
102    // Only initialize logging once
103    static INIT: std::sync::Once = std::sync::Once::new();
104    INIT.call_once(|| {
105        use tracing_subscriber::EnvFilter;
106
107        let default_level = if verbose {
108            "fastskill=info"
109        } else {
110            "fastskill=warn"
111        };
112        let filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| default_level.into());
113
114        let subscriber = tracing_subscriber::fmt().with_env_filter(filter).finish();
115
116        // This will fail silently if already initialized
117        let _ = tracing::subscriber::set_global_default(subscriber);
118    });
119}
120
121pub mod test_utils;
122
123#[cfg(test)]
124#[allow(clippy::unwrap_used)]
125mod tests {
126    use super::*;
127    use tempfile::TempDir;
128
129    #[tokio::test]
130    async fn test_service_initialization() {
131        let temp_dir = TempDir::new().unwrap();
132        let config = ServiceConfig {
133            skill_storage_path: temp_dir.path().to_path_buf(),
134            ..Default::default()
135        };
136
137        let service = FastSkillService::new(config).await.unwrap();
138        assert!(service.skill_manager().list_skills(None).await.is_ok());
139    }
140}