Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/fastskill-cli/src/commands/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ pub async fn execute_list(

// Installed skills from service
let skill_manager = service.skill_manager();
let installed_skills = skill_manager.list_skills(None).await.map_err(|e| {
let installed_skills = skill_manager.list_skills().await.map_err(|e| {
CliError::Service(fastskill_core::ServiceError::Custom(format!(
"Failed to list installed skills: {}",
e
Expand Down
4 changes: 2 additions & 2 deletions crates/fastskill-cli/src/commands/read.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ async fn resolve_skill(
// Check for partial matches
let all_skills = service
.skill_manager()
.list_skills(None)
.list_skills()
.await
.map_err(CliError::Service)?;

Expand Down Expand Up @@ -371,7 +371,7 @@ pub async fn execute_read(service: Arc<FastSkillService>, args: ReadArgs) -> Cli
// T024: If no exact match, check for multiple partial matches
let all_skills = service
.skill_manager()
.list_skills(None)
.list_skills()
.await
.map_err(CliError::Service)?;

Expand Down
1 change: 0 additions & 1 deletion crates/fastskill-cli/tests/lock_determinism_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ fn make_skill(id: &str) -> SkillDefinition {
description: "test".to_string(),
version: "1.0.0".to_string(),
author: None,
enabled: true,
created_at: Utc::now(),
updated_at: Utc::now(),
skill_file: std::path::PathBuf::from("SKILL.md"),
Expand Down
1 change: 0 additions & 1 deletion crates/fastskill-cli/tests/lock_scope_routing_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ fn make_skill(id: &str) -> SkillDefinition {
description: "test".to_string(),
version: "1.0.0".to_string(),
author: None,
enabled: true,
created_at: Utc::now(),
updated_at: Utc::now(),
skill_file: std::path::PathBuf::from("SKILL.md"),
Expand Down
1 change: 0 additions & 1 deletion crates/fastskill-core/src/core/lock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,6 @@ mod tests {
description: "test".to_string(),
version: "1.0.0".to_string(),
author: None,
enabled: true,
created_at: Utc::now(),
updated_at: Utc::now(),
skill_file: std::path::PathBuf::from("SKILL.md"),
Expand Down
27 changes: 23 additions & 4 deletions crates/fastskill-core/src/core/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ pub struct SkillMetadata {
pub description: String,
pub version: String,
pub author: Option<String>,
pub enabled: bool,
pub token_estimate: usize,
pub last_updated: chrono::DateTime<chrono::Utc>,
}
Expand All @@ -26,8 +25,7 @@ impl From<&SkillDefinition> for SkillMetadata {
description: skill.description.clone(),
version: skill.version.clone(),
author: skill.author.clone(),
enabled: skill.enabled,
token_estimate: skill.description.len() / 4, // Rough estimate
token_estimate: skill.description.len() / 4,
last_updated: skill.updated_at,
}
}
Expand Down Expand Up @@ -229,7 +227,7 @@ pub fn parse_yaml_frontmatter(content: &str) -> Result<SkillFrontmatter, Service
#[async_trait]
impl MetadataService for MetadataServiceImpl {
async fn discover_skills(&self, query: &str) -> Result<Vec<SkillMetadata>, ServiceError> {
let all_skills = self.skill_manager.list_skills(None).await?;
let all_skills = self.skill_manager.list_skills().await?;

// Filter and score skills based on query relevance
let mut scored_skills: Vec<(f32, &SkillDefinition)> = all_skills
Expand Down Expand Up @@ -285,3 +283,24 @@ impl MetadataService for MetadataServiceImpl {
self.parse_frontmatter(&content)
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_frontmatter_with_legacy_enabled_key() {
let content =
"---\nname: test-skill\ndescription: A test skill\nenabled: true\n---\n# Body";
let result = parse_yaml_frontmatter(content);
assert!(
result.is_ok(),
"parse_yaml_frontmatter should succeed with legacy enabled key"
);
let fm = result.unwrap();
assert!(
fm.extra.contains_key("enabled"),
"extra map should contain the enabled key"
);
}
}
2 changes: 1 addition & 1 deletion crates/fastskill-core/src/core/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ pub use service::{

// skill_manager
pub use skill_manager::{
SkillDefinition, SkillFilters, SkillManagementService, SkillManager, SkillUpdate, SourceType,
SkillDefinition, SkillManagementService, SkillManager, SkillUpdate, SourceType,
};

// sources
Expand Down
3 changes: 0 additions & 3 deletions crates/fastskill-core/src/core/repository/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,6 @@ impl RepositoryClient for MarketplaceRepositoryClient {
description: info.description,
version: info.version.unwrap_or_else(|| "1.0.0".to_string()),
author: None,
enabled: true,
token_estimate: 0,
last_updated: Utc::now(),
})
Expand Down Expand Up @@ -439,7 +438,6 @@ impl RepositoryClient for CratesRegistryClient {
description: s.description.clone(),
version: s.latest_version.clone(),
author: None, // Not available in SkillSummary
enabled: true,
token_estimate: s.description.len() / 4, // Rough estimate
last_updated: s.published_at.unwrap_or_else(chrono::Utc::now),
})
Expand Down Expand Up @@ -488,7 +486,6 @@ impl RepositoryClient for CratesRegistryClient {
.unwrap_or_else(|| "".to_string()),
version: e.vers,
author: e.metadata.as_ref().and_then(|m| m.author.clone()),
enabled: true,
token_estimate: 0,
last_updated: Utc::now(),
})
Expand Down
56 changes: 3 additions & 53 deletions crates/fastskill-core/src/core/skill_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ pub struct SkillDefinition {
pub description: String,
pub version: String,
pub author: Option<String>,
pub enabled: bool,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,

Expand Down Expand Up @@ -63,7 +62,6 @@ impl SkillDefinition {
description,
version,
author: None,
enabled: true,
created_at: now,
updated_at: now,
skill_file: std::path::PathBuf::from(format!("./skills/{}/SKILL.md", id)),
Expand Down Expand Up @@ -99,12 +97,7 @@ pub trait SkillManagementService: Send + Sync {
updates: SkillUpdate,
) -> Result<(), ServiceError>;
async fn unregister_skill(&self, skill_id: &SkillId) -> Result<(), ServiceError>;
async fn list_skills(
&self,
filters: Option<SkillFilters>,
) -> Result<Vec<SkillDefinition>, ServiceError>;
async fn enable_skill(&self, skill_id: &SkillId) -> Result<(), ServiceError>;
async fn disable_skill(&self, skill_id: &SkillId) -> Result<(), ServiceError>;
async fn list_skills(&self) -> Result<Vec<SkillDefinition>, ServiceError>;
}

#[derive(Debug)]
Expand All @@ -126,18 +119,12 @@ impl SkillManager {
}
}

#[derive(Debug, Clone)]
pub struct SkillFilters {
pub enabled: Option<bool>,
}

#[derive(Debug, Clone, Default)]
pub struct SkillUpdate {
pub name: Option<String>,
pub description: Option<String>,
pub version: Option<String>,
pub author: Option<String>,
pub enabled: Option<bool>,
pub source_url: Option<String>,
pub source_type: Option<SourceType>,
pub source_branch: Option<String>,
Expand Down Expand Up @@ -197,9 +184,6 @@ impl SkillManagementService for SkillManager {
if let Some(author) = updates.author {
skill.author = Some(author);
}
if let Some(enabled) = updates.enabled {
skill.enabled = enabled;
}
if let Some(source_url) = updates.source_url {
skill.source_url = Some(source_url);
}
Expand Down Expand Up @@ -244,42 +228,8 @@ impl SkillManagementService for SkillManager {
}
}

async fn list_skills(
&self,
filters: Option<SkillFilters>,
) -> Result<Vec<SkillDefinition>, ServiceError> {
async fn list_skills(&self) -> Result<Vec<SkillDefinition>, ServiceError> {
let skills = self.skills.read().await;
let mut filtered_skills: Vec<SkillDefinition> = skills.values().cloned().collect();

if let Some(filters) = filters {
// Filter by enabled status
if let Some(enabled) = filters.enabled {
filtered_skills.retain(|skill| skill.enabled == enabled);
}
}

Ok(filtered_skills)
}

async fn enable_skill(&self, skill_id: &SkillId) -> Result<(), ServiceError> {
self.update_skill(
skill_id,
SkillUpdate {
enabled: Some(true),
..Default::default()
},
)
.await
}

async fn disable_skill(&self, skill_id: &SkillId) -> Result<(), ServiceError> {
self.update_skill(
skill_id,
SkillUpdate {
enabled: Some(false),
..Default::default()
},
)
.await
Ok(skills.values().cloned().collect())
}
}
29 changes: 0 additions & 29 deletions crates/fastskill-core/src/events/event_bus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,6 @@ pub enum SkillEvent {
/// Hot reload disabled
HotReloadDisabled,

/// Skill enabled
SkillEnabled { skill_id: String },

/// Skill disabled
SkillDisabled { skill_id: String },

/// Custom event
Custom {
event_type: String,
Expand All @@ -68,7 +62,6 @@ pub struct SkillUpdate {
pub name: Option<String>,
pub description: Option<String>,
pub version: Option<String>,
pub enabled: Option<bool>,
}

/// Hot reload configuration
Expand Down Expand Up @@ -204,8 +197,6 @@ impl EventBus {
SkillEvent::SkillValidationFailed { .. } => "skill:validation:failed",
SkillEvent::HotReloadEnabled { .. } => "hot-reload:enabled",
SkillEvent::HotReloadDisabled => "hot-reload:disabled",
SkillEvent::SkillEnabled { .. } => "skill:enabled",
SkillEvent::SkillDisabled { .. } => "skill:disabled",
SkillEvent::Custom { event_type, .. } => event_type.as_str(),
}
.to_string();
Expand Down Expand Up @@ -300,12 +291,6 @@ impl EventHandler for LoggingEventHandler {
SkillEvent::HotReloadDisabled => {
info!("Hot reload disabled");
}
SkillEvent::SkillEnabled { skill_id } => {
info!("[OK] Skill enabled: {}", skill_id);
}
SkillEvent::SkillDisabled { skill_id } => {
info!("Skill disabled: {}", skill_id);
}
SkillEvent::Custom { event_type, data } => {
debug!("Custom event: {} - {:?}", event_type, data);
}
Expand Down Expand Up @@ -350,8 +335,6 @@ impl EventHandler for MetricsEventHandler {
SkillEvent::SkillValidationFailed { .. } => "skill:validation:failed".to_string(),
SkillEvent::HotReloadEnabled { .. } => "hot-reload:enabled".to_string(),
SkillEvent::HotReloadDisabled => "hot-reload:disabled".to_string(),
SkillEvent::SkillEnabled { .. } => "skill:enabled".to_string(),
SkillEvent::SkillDisabled { .. } => "skill:disabled".to_string(),
SkillEvent::Custom { event_type, .. } => event_type.clone(),
};

Expand Down Expand Up @@ -434,16 +417,4 @@ impl EventBus {
pub async fn publish_hot_reload_disabled(&self) -> Result<usize, ServiceError> {
self.publish_event(SkillEvent::HotReloadDisabled).await
}

/// Publish skill enabled event
pub async fn publish_skill_enabled(&self, skill_id: String) -> Result<usize, ServiceError> {
self.publish_event(SkillEvent::SkillEnabled { skill_id })
.await
}

/// Publish skill disabled event
pub async fn publish_skill_disabled(&self, skill_id: String) -> Result<usize, ServiceError> {
self.publish_event(SkillEvent::SkillDisabled { skill_id })
.await
}
}
4 changes: 2 additions & 2 deletions crates/fastskill-core/src/http/handlers/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ pub async fn list_all_skills(

// Get all installed skills
let installed_skills = skill_manager
.list_skills(None)
.list_skills()
.await
.map_err(|e| HttpError::InternalServerError(e.to_string()))?;

Expand Down Expand Up @@ -306,7 +306,7 @@ pub async fn list_source_skills(

// Get installed skills to check installation status
let installed_skills = skill_manager
.list_skills(None)
.list_skills()
.await
.map_err(|e| HttpError::InternalServerError(e.to_string()))?;

Expand Down
2 changes: 1 addition & 1 deletion crates/fastskill-core/src/http/handlers/search.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ pub async fn search_skills(
let skills_list = state
.service
.skill_manager()
.list_skills(None)
.list_skills()
.await
.map_err(|e| HttpError::ServiceError(format!("Failed to list skills: {}", e)))?;

Expand Down
7 changes: 3 additions & 4 deletions crates/fastskill-core/src/http/handlers/skills.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ fn skill_metadata_json(skill: &crate::core::skill_manager::SkillDefinition) -> s
"description": skill.description,
"version": skill.version,
"author": skill.author,
"enabled": skill.enabled,
"created_at": skill.created_at.to_rfc3339(),
"updated_at": skill.updated_at.to_rfc3339(),
"skill_file": skill.skill_file,
Expand All @@ -42,7 +41,7 @@ fn skill_metadata_json(skill: &crate::core::skill_manager::SkillDefinition) -> s
pub async fn list_skills(
State(state): State<AppState>,
) -> HttpResult<axum::Json<ApiResponse<SkillsListResponse>>> {
let skills = state.service.skill_manager().list_skills(None).await?;
let skills = state.service.skill_manager().list_skills().await?;

let skill_responses: Vec<SkillResponse> = skills
.clone()
Expand Down Expand Up @@ -73,7 +72,7 @@ pub async fn get_skill(
) -> HttpResult<axum::Json<ApiResponse<SkillResponse>>> {
// Check permissions

let skills = state.service.skill_manager().list_skills(None).await?;
let skills = state.service.skill_manager().list_skills().await?;
let skill_id_parsed = crate::core::service::SkillId::new(skill_id.clone())
.map_err(|_| HttpError::BadRequest("Invalid skill ID format".to_string()))?;
let skill = skills
Expand Down Expand Up @@ -174,7 +173,7 @@ pub async fn delete_skill(
let skill_id_parsed = crate::core::service::SkillId::new(skill_id.clone())
.map_err(|_| HttpError::BadRequest("Invalid skill ID format".to_string()))?;

let skills = state.service.skill_manager().list_skills(None).await?;
let skills = state.service.skill_manager().list_skills().await?;
let skill = skills
.into_iter()
.find(|s| s.id == skill_id_parsed)
Expand Down
5 changes: 2 additions & 3 deletions crates/fastskill-core/src/http/handlers/status.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,7 @@ impl AppState {

/// GET / - Root endpoint with HTML dashboard
pub async fn root(State(state): State<AppState>) -> Html<String> {
let skills: Vec<_> =
(state.service.skill_manager().list_skills(None).await).unwrap_or_default();
let skills: Vec<_> = (state.service.skill_manager().list_skills().await).unwrap_or_default();

let skills_count = skills.len();
let uptime = state.uptime_seconds();
Expand Down Expand Up @@ -238,7 +237,7 @@ pub async fn root(State(state): State<AppState>) -> Html<String> {
pub async fn status(
State(state): State<AppState>,
) -> HttpResult<axum::Json<ApiResponse<StatusResponse>>> {
let skills = state.service.skill_manager().list_skills(None).await?;
let skills = state.service.skill_manager().list_skills().await?;
let skills_count = skills.len();

let config = state.service.config();
Expand Down
Loading
Loading