feat: add tool manager capability

This commit is contained in:
2026-06-22 10:30:12 +08:00
parent 99c1e9cd6c
commit 32c4fcf3a8
11 changed files with 590 additions and 46 deletions
+68
View File
@@ -12,6 +12,7 @@ use crate::tools::executor;
use crate::tools::parser;
use crate::tools::spec::ToolSpec;
use serde_json::Value;
use tokio::sync::RwLock;
#[derive(Debug, Clone, serde::Serialize)]
pub struct ToolSummary {
@@ -53,6 +54,11 @@ pub struct Registry {
tools: HashMap<String, ToolSpec>,
}
pub struct RegistryManager {
root: String,
registry: RwLock<Registry>,
}
impl Registry {
/// 扫描工具根目录下各子目录的 `specs/*.tool.yaml`。
pub fn load(dir: &str) -> Self {
@@ -176,6 +182,68 @@ impl Registry {
}
}
impl RegistryManager {
pub fn load(dir: impl Into<String>) -> Self {
let root = dir.into();
Self {
registry: RwLock::new(Registry::load(&root)),
root,
}
}
pub async fn reload(&self) -> usize {
let registry = Registry::load(&self.root);
let len = registry.len();
*self.registry.write().await = registry;
len
}
pub async fn list_tools(&self) -> Vec<ToolSummary> {
self.registry.read().await.list_tools()
}
pub async fn dispatch(
&self,
name: &str,
params: &Value,
user_id: &str,
approved: bool,
approval: &Arc<ApprovalManager>,
memory: &Arc<MemoryStore>,
wechat_send: &(
dyn Fn(&str, &str) -> std::pin::Pin<Box<dyn std::future::Future<Output = ()> + Send>>
+ Send
+ Sync
),
) -> String {
let spec = {
let registry = self.registry.read().await;
match registry.get(name) {
Some(spec) => spec.clone(),
None => {
tracing::warn!(target:"ias::registry","未知: {name}");
return format!("未知工具: {name}");
}
}
};
if let Some(err) = validate_required_params(&spec, params) {
return err;
}
executor::execute_loop(
&spec,
params,
user_id,
approved,
approval,
memory,
wechat_send,
)
.await
}
}
fn validate_required_params(spec: &ToolSpec, params: &Value) -> Option<String> {
let Some(obj) = params.as_object() else {
return Some(format!("工具 '{}' 参数必须是 JSON 对象", spec.name));