Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
refactor(loop_guard): 为LoopGuard添加Clone派生 feat(capabilities): 实现CapabilityManager.validate()安全验证 fix(agentStore): 添加token用量追踪 chore: 删除未实现的Predictor/Lead HAND.toml文件 style(Credits): 移除假数据并标注开发中状态 refactor(Skills): 动态加载技能卡片 perf(configStore): 为定时任务添加localStorage降级 docs: 更新功能文档和版本变更记录
94 lines
2.9 KiB
Rust
94 lines
2.9 KiB
Rust
//! Capability manager
|
|
|
|
use dashmap::DashMap;
|
|
use zclaw_types::{AgentId, Capability, CapabilitySet, Result, ZclawError};
|
|
|
|
/// Manages capabilities for all agents
|
|
pub struct CapabilityManager {
|
|
capabilities: DashMap<AgentId, CapabilitySet>,
|
|
}
|
|
|
|
impl CapabilityManager {
|
|
pub fn new() -> Self {
|
|
Self {
|
|
capabilities: DashMap::new(),
|
|
}
|
|
}
|
|
|
|
/// Grant capabilities to an agent
|
|
pub fn grant(&self, agent_id: AgentId, capabilities: Vec<Capability>) {
|
|
let set = CapabilitySet {
|
|
capabilities,
|
|
};
|
|
self.capabilities.insert(agent_id, set);
|
|
}
|
|
|
|
/// Revoke all capabilities from an agent
|
|
pub fn revoke(&self, agent_id: &AgentId) {
|
|
self.capabilities.remove(agent_id);
|
|
}
|
|
|
|
/// Check if an agent can invoke a tool
|
|
pub fn can_invoke_tool(&self, agent_id: &AgentId, tool_name: &str) -> bool {
|
|
self.capabilities
|
|
.get(agent_id)
|
|
.map(|set| set.can_invoke_tool(tool_name))
|
|
.unwrap_or(false)
|
|
}
|
|
|
|
/// Check if an agent can read memory
|
|
pub fn can_read_memory(&self, agent_id: &AgentId, scope: &str) -> bool {
|
|
self.capabilities
|
|
.get(agent_id)
|
|
.map(|set| set.can_read_memory(scope))
|
|
.unwrap_or(false)
|
|
}
|
|
|
|
/// Check if an agent can write memory
|
|
pub fn can_write_memory(&self, agent_id: &AgentId, scope: &str) -> bool {
|
|
self.capabilities
|
|
.get(agent_id)
|
|
.map(|set| set.can_write_memory(scope))
|
|
.unwrap_or(false)
|
|
}
|
|
|
|
/// Validate capabilities for dangerous combinations
|
|
///
|
|
/// Checks that overly broad capabilities are not combined with
|
|
/// dangerous operations. Returns an error if an unsafe combination
|
|
/// is detected.
|
|
pub fn validate(&self, capabilities: &[Capability]) -> Result<()> {
|
|
let has_tool_all = capabilities.iter().any(|c| matches!(c, Capability::ToolAll));
|
|
let has_agent_kill = capabilities.iter().any(|c| matches!(c, Capability::AgentKill { .. }));
|
|
let has_shell_wildcard = capabilities.iter().any(|c| {
|
|
matches!(c, Capability::ShellExec { pattern } if pattern == "*")
|
|
});
|
|
|
|
// ToolAll + destructive operations is dangerous
|
|
if has_tool_all && has_agent_kill {
|
|
return Err(ZclawError::SecurityError(
|
|
"ToolAll 与 AgentKill 不能同时授予".to_string(),
|
|
));
|
|
}
|
|
|
|
if has_tool_all && has_shell_wildcard {
|
|
return Err(ZclawError::SecurityError(
|
|
"ToolAll 与 ShellExec(\"*\") 不能同时授予".to_string(),
|
|
));
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Get capabilities for an agent
|
|
pub fn get(&self, agent_id: &AgentId) -> Option<CapabilitySet> {
|
|
self.capabilities.get(agent_id).map(|c| c.clone())
|
|
}
|
|
}
|
|
|
|
impl Default for CapabilityManager {
|
|
fn default() -> Self {
|
|
Self::new()
|
|
}
|
|
}
|