openfunctions_rs/core/
registry.rs1use crate::core::{Agent, Tool};
4use anyhow::Result;
5use std::collections::HashMap;
6use std::path::PathBuf;
7use tracing::{info, warn};
8
9#[derive(Debug, Default)]
14pub struct Registry {
15 tools: HashMap<String, Tool>,
16 agents: HashMap<String, Agent>,
17}
18
19impl Registry {
20 pub fn new() -> Self {
22 Self::default()
23 }
24
25 pub async fn load_tools(&mut self, tool_dirs: &[PathBuf]) -> Result<()> {
30 info!(dirs = ?tool_dirs, "Loading tools from directories");
31 for dir in tool_dirs {
32 if !dir.exists() {
33 warn!(dir = %dir.display(), "Tool directory not found, skipping");
34 continue;
35 }
36 if dir.is_dir() {
37 let mut entries = tokio::fs::read_dir(dir).await?;
38 while let Some(entry) = entries.next_entry().await? {
39 let path = entry.path();
40 if path.is_file() {
41 if let Some(ext) = path.extension() {
42 if matches!(ext.to_str(), Some("sh" | "js" | "py")) {
43 match Tool::from_file(&path).await {
44 Ok(tool) => {
45 info!(name = %tool.name, "Loaded tool");
46 self.tools.insert(tool.name.clone(), tool);
47 }
48 Err(e) => {
49 warn!(path = %path.display(), error = ?e, "Failed to load tool");
50 }
51 }
52 }
53 }
54 }
55 }
56 }
57 }
58
59 Ok(())
60 }
61
62 pub async fn load_agents(&mut self, agent_dirs: &[PathBuf]) -> Result<()> {
67 info!(dirs = ?agent_dirs, "Loading agents from directories");
68 for dir in agent_dirs {
69 if !dir.exists() {
70 warn!(dir = %dir.display(), "Agent directory not found, skipping");
71 continue;
72 }
73 if dir.is_dir() {
74 let mut entries = tokio::fs::read_dir(dir).await?;
75 while let Some(entry) = entries.next_entry().await? {
76 let path = entry.path();
77 if path.is_dir() {
78 match Agent::from_directory(&path).await {
79 Ok(agent) => {
80 info!(name = %agent.name, "Loaded agent");
81 self.agents.insert(agent.name.clone(), agent);
82 }
83 Err(e) => {
84 warn!(path = %path.display(), error = ?e, "Failed to load agent");
85 }
86 }
87 }
88 }
89 }
90 }
91
92 Ok(())
93 }
94
95 pub fn get_tool(&self, name: &str) -> Option<&Tool> {
97 self.tools.get(name)
98 }
99
100 pub fn get_agent(&self, name: &str) -> Option<&Agent> {
102 self.agents.get(name)
103 }
104
105 pub fn list_tools(&self) -> Vec<String> {
107 self.tools.keys().cloned().collect()
108 }
109
110 pub fn list_agents(&self) -> Vec<String> {
112 self.agents.keys().cloned().collect()
113 }
114}