gitai/server/tools/
utils.rs1use crate::common::DetailLevel;
6use crate::config::Config as PilotConfig;
7use crate::git::GitRepo;
8use rmcp::model::{Annotated, CallToolResult, Content, RawContent, RawTextContent};
9use std::sync::Arc;
10
11#[async_trait::async_trait]
15pub trait PilotTool {
16 async fn execute(
18 &self,
19 git_repo: Arc<GitRepo>,
20 config: PilotConfig,
21 ) -> Result<CallToolResult, anyhow::Error>;
22}
23
24pub fn create_text_result(text: String) -> CallToolResult {
28 CallToolResult {
29 content: vec![Content::from(Annotated {
30 raw: RawContent::Text(RawTextContent {
31 text,
32 meta: Option::default(),
33 }),
34 annotations: None,
35 })],
36 is_error: None,
37 meta: Option::default(),
38 structured_content: None,
39 }
40}
41
42pub fn parse_detail_level(detail_level: &str) -> DetailLevel {
46 if detail_level.trim().is_empty() {
47 return DetailLevel::Standard;
48 }
49
50 match detail_level.trim().to_lowercase().as_str() {
51 "minimal" => DetailLevel::Minimal,
52 "detailed" => DetailLevel::Detailed,
53 _ => DetailLevel::Standard,
54 }
55}
56
57pub fn apply_custom_instructions(config: &mut crate::config::Config, custom_instructions: &str) {
59 if !custom_instructions.trim().is_empty() {
60 config.set_temp_instructions(Some(custom_instructions.to_string()));
61 }
62}
63
64pub fn validate_repository_parameter(repo: &str) -> Result<(), anyhow::Error> {
66 if repo.trim().is_empty() {
67 return Err(anyhow::anyhow!(
68 "The `repository` parameter is required and must be a valid local path or remote URL."
69 ));
70 }
71 if !(repo.starts_with("http://") || repo.starts_with("https://") || repo.starts_with("git@")) {
72 let path = std::path::Path::new(repo);
73 if !path.exists() {
74 return Err(anyhow::anyhow!(format!(
75 "The specified repository path does not exist: {repo}"
76 )));
77 }
78 if !path.join(".git").exists() {
79 return Err(anyhow::anyhow!(format!(
80 "The specified path is not a git repository: {repo}"
81 )));
82 }
83 }
84 Ok(())
85}
86
87pub fn resolve_git_repo(
92 repo_path: Option<&str>,
93 _default_git_repo: Arc<GitRepo>,
94) -> Result<Arc<GitRepo>, anyhow::Error> {
95 match repo_path {
96 Some(path) if !path.trim().is_empty() => {
97 if path.starts_with("http://")
98 || path.starts_with("https://")
99 || path.starts_with("git@")
100 {
101 Ok(Arc::new(GitRepo::new_from_url(Some(path.to_string()))?))
103 } else {
104 let path = std::path::Path::new(path);
106 Ok(Arc::new(GitRepo::new(path)?))
107 }
108 }
109 _ => Err(anyhow::anyhow!(
110 "The `repository` parameter is required and must be a valid local path or remote URL."
111 )),
112 }
113}