feat: add tool manager capability
This commit is contained in:
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user