git_iris/agents/tools/
common.rs1use std::future::Future;
9use std::path::{Path, PathBuf};
10
11use serde_json::{Map, Value};
12
13use crate::git::GitRepo;
14
15tokio::task_local! {
16 static ACTIVE_REPO_ROOT: PathBuf;
17}
18
19#[must_use]
26pub fn parameters_schema<T: schemars::JsonSchema>() -> Value {
27 use schemars::schema_for;
28
29 let schema = schema_for!(T);
30 let mut value = serde_json::to_value(schema).expect("tool schema should serialize");
31 enforce_required_properties(&mut value);
32 value
33}
34
35fn enforce_required_properties(value: &mut Value) {
38 let Some(obj) = value.as_object_mut() else {
39 return;
40 };
41
42 let props_entry = obj
43 .entry("properties")
44 .or_insert_with(|| Value::Object(Map::new()));
45 let props_obj = props_entry.as_object().expect("properties must be object");
46 let required_keys: Vec<Value> = props_obj.keys().cloned().map(Value::String).collect();
47
48 obj.insert("required".to_string(), Value::Array(required_keys));
49}
50
51pub fn get_current_repo() -> anyhow::Result<GitRepo> {
58 let repo_root = current_repo_root()?;
59 GitRepo::new(&repo_root)
60}
61
62pub async fn with_active_repo_root<F, T>(repo_path: &Path, future: F) -> T
64where
65 F: Future<Output = T>,
66{
67 ACTIVE_REPO_ROOT
68 .scope(repo_path.to_path_buf(), future)
69 .await
70}
71
72pub fn current_repo_root() -> anyhow::Result<PathBuf> {
78 if let Ok(repo_root) = ACTIVE_REPO_ROOT.try_with(Clone::clone) {
79 return Ok(repo_root);
80 }
81
82 let current_dir = std::env::current_dir()?;
83 let repo = GitRepo::new(¤t_dir)?;
84 Ok(repo.repo_path().clone())
85}
86
87#[macro_export]
101macro_rules! define_tool_error {
102 ($name:ident) => {
103 #[derive(Debug)]
104 pub struct $name(pub String);
105
106 impl std::fmt::Display for $name {
107 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
108 write!(f, "{}", self.0)
109 }
110 }
111
112 impl std::error::Error for $name {}
113
114 impl From<anyhow::Error> for $name {
115 fn from(err: anyhow::Error) -> Self {
116 $name(err.to_string())
117 }
118 }
119
120 impl From<std::io::Error> for $name {
121 fn from(err: std::io::Error) -> Self {
122 $name(err.to_string())
123 }
124 }
125 };
126}
127
128pub use define_tool_error;