use crate::core::capability::CapabilityRegistry;
use crate::core::tool::ToolRegistry;
use crate::domain::capability::{Capability, CapabilityAccessType, SkillCapabilityBinding};
use crate::domain::{Skill, SkillToolBinding, Tool, ToolAccessType};
use anyhow::Result;
use dashmap::DashMap;
use std::sync::Arc;
pub struct SkillManager {
skills: DashMap<String, Skill>,
skill_tool_bindings: DashMap<String, Vec<SkillToolBinding>>, tool_skill_bindings: DashMap<String, Vec<String>>, tool_access_control: DashMap<String, ToolAccessType>,
skill_capability_bindings: DashMap<String, Vec<SkillCapabilityBinding>>, capability_skill_bindings: DashMap<String, Vec<String>>, capability_access_control: DashMap<String, CapabilityAccessType>,
tool_registry: Arc<ToolRegistry>,
capability_registry: Arc<CapabilityRegistry>,
}
impl SkillManager {
pub fn new(
tool_registry: Arc<ToolRegistry>,
capability_registry: Arc<CapabilityRegistry>,
) -> Self {
Self {
skills: DashMap::new(),
skill_tool_bindings: DashMap::new(),
tool_skill_bindings: DashMap::new(),
tool_access_control: DashMap::new(),
skill_capability_bindings: DashMap::new(),
capability_skill_bindings: DashMap::new(),
capability_access_control: DashMap::new(),
tool_registry,
capability_registry,
}
}
pub fn new_with_tool_registry(tool_registry: Arc<ToolRegistry>) -> Self {
let capability_registry = Arc::new(CapabilityRegistry::new());
Self::new(tool_registry, capability_registry)
}
pub fn new_with_registries(
tool_registry: Arc<ToolRegistry>,
capability_registry: Arc<CapabilityRegistry>,
) -> Self {
Self::new(tool_registry, capability_registry)
}
pub fn new_with_capability_registry(capability_registry: Arc<CapabilityRegistry>) -> Self {
let tool_registry = Arc::new(ToolRegistry::new());
Self::new(tool_registry, capability_registry)
}
pub fn register_skill(&self, skill: Skill) -> Result<()> {
if self.skills.contains_key(&skill.id) {
return Err(anyhow::anyhow!("Skill already registered: {}", skill.id));
}
self.skills.insert(skill.id.clone(), skill);
Ok(())
}
pub fn set_tool_access(&self, tool_id: &str, access_type: ToolAccessType) -> Result<()> {
self.tool_access_control
.insert(tool_id.to_string(), access_type);
Ok(())
}
pub fn set_capability_access(
&self,
capability_id: &str,
access_type: CapabilityAccessType,
) -> Result<()> {
if !self.capability_registry.contains(capability_id) {
return Err(anyhow::anyhow!("Capability not found: {}", capability_id));
}
self.capability_access_control
.insert(capability_id.to_string(), access_type);
Ok(())
}
pub fn bind_skill_tool(&self, binding: SkillToolBinding) -> Result<()> {
if !self.skills.contains_key(&binding.skill_id) {
return Err(anyhow::anyhow!("Skill not found: {}", binding.skill_id));
}
self.skill_tool_bindings
.entry(binding.skill_id.clone())
.or_default()
.push(binding.clone());
self.tool_skill_bindings
.entry(binding.tool_id.clone())
.or_default()
.push(binding.skill_id.clone());
if !self.tool_access_control.contains_key(&binding.tool_id) {
self.tool_access_control
.insert(binding.tool_id.clone(), ToolAccessType::Private);
}
Ok(())
}
pub fn bind_skill_capability(&self, binding: SkillCapabilityBinding) -> Result<()> {
if !self.skills.contains_key(&binding.skill_id) {
return Err(anyhow::anyhow!("Skill not found: {}", binding.skill_id));
}
if !self.capability_registry.contains(&binding.capability_id) {
return Err(anyhow::anyhow!(
"Capability not found: {}",
binding.capability_id
));
}
self.skill_capability_bindings
.entry(binding.skill_id.clone())
.or_default()
.push(binding.clone());
self.capability_skill_bindings
.entry(binding.capability_id.clone())
.or_default()
.push(binding.skill_id.clone());
if !self
.capability_access_control
.contains_key(&binding.capability_id)
{
self.capability_access_control
.insert(binding.capability_id.clone(), CapabilityAccessType::Private);
}
Ok(())
}
pub fn get_skill_tools(&self, skill_id: &str) -> Vec<Tool> {
let mut tools = Vec::new();
if let Some(bindings) = self.skill_tool_bindings.get(skill_id) {
for binding in bindings.value() {
if let Some(tool) = self.tool_registry.get(&binding.tool_id) {
tools.push(tool);
}
}
}
tools
}
pub fn get_skill_capabilities(&self, skill_id: &str) -> Vec<Capability> {
let mut capabilities = Vec::new();
if let Some(bindings) = self.skill_capability_bindings.get(skill_id) {
for binding in bindings.value() {
if let Some(capability) = self.capability_registry.get(&binding.capability_id) {
capabilities.push(capability);
}
}
}
capabilities
}
pub fn can_call_tool(&self, tool_id: &str, caller_skills: &[String]) -> bool {
if !self.tool_registry.contains(tool_id) {
return false;
}
let access_type = self
.tool_access_control
.get(tool_id)
.map(|v| v.value().clone())
.unwrap_or(ToolAccessType::Public);
match access_type {
ToolAccessType::Public => true,
ToolAccessType::Private => {
if let Some(allowed_skills) = self.tool_skill_bindings.get(tool_id) {
caller_skills
.iter()
.any(|skill| allowed_skills.value().contains(skill))
} else {
false
}
}
}
}
pub fn can_call_capability(&self, capability_id: &str, caller_skills: &[String]) -> bool {
if !self.capability_registry.contains(capability_id) {
return false;
}
let access_type = self
.capability_access_control
.get(capability_id)
.map(|v| v.value().clone())
.unwrap_or(CapabilityAccessType::Public);
match access_type {
CapabilityAccessType::Public => true,
CapabilityAccessType::Private => {
if let Some(allowed_skills) = self.capability_skill_bindings.get(capability_id) {
caller_skills
.iter()
.any(|skill| allowed_skills.value().contains(skill))
} else {
false
}
}
}
}
pub fn get_skills(&self) -> Vec<Skill> {
self.skills.iter().map(|kv| kv.value().clone()).collect()
}
pub fn get_skill(&self, skill_id: &str) -> Option<Skill> {
self.skills.get(skill_id).map(|s| s.clone())
}
pub fn get_tool_bound_skills(&self, tool_id: &str) -> Vec<String> {
self.tool_skill_bindings
.get(tool_id)
.map(|skills| skills.value().clone())
.unwrap_or_default()
}
pub fn get_capability_bound_skills(&self, capability_id: &str) -> Vec<String> {
self.capability_skill_bindings
.get(capability_id)
.map(|skills| skills.value().clone())
.unwrap_or_default()
}
pub fn get_skill_bound_tools(&self, skill_id: &str) -> Vec<String> {
self.skill_tool_bindings
.get(skill_id)
.map(|bindings| {
bindings
.value()
.iter()
.map(|binding| binding.tool_id.clone())
.collect()
})
.unwrap_or_default()
}
pub fn get_skill_bound_capabilities(&self, skill_id: &str) -> Vec<String> {
self.skill_capability_bindings
.get(skill_id)
.map(|bindings| {
bindings
.value()
.iter()
.map(|binding| binding.capability_id.clone())
.collect()
})
.unwrap_or_default()
}
pub fn get_skill_ids(&self) -> Vec<String> {
self.skills.iter().map(|kv| kv.key().clone()).collect()
}
pub fn get_tool_ids(&self) -> Vec<String> {
self.tool_registry
.list_all()
.iter()
.map(|t| t.id.clone())
.collect()
}
pub fn get_capability_ids(&self) -> Vec<String> {
self.capability_registry
.list_all()
.iter()
.map(|c| c.id.clone())
.collect()
}
}