128 lines
3.7 KiB
Rust
128 lines
3.7 KiB
Rust
use reqwest::Client;
|
|
use serde::{Deserialize, Serialize};
|
|
use serde_json::Value;
|
|
use std::error::Error;
|
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
pub struct MCPRequest {
|
|
pub method: String,
|
|
pub params: Value,
|
|
pub context: ProjectContext,
|
|
}
|
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
pub struct ProjectContext {
|
|
pub current_dir: String,
|
|
pub project_type: Option<String>, // rust, python, node, etc.
|
|
pub files: Vec<String>,
|
|
pub git_branch: Option<String>,
|
|
}
|
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
pub struct MCPResponse {
|
|
pub result: Option<Value>,
|
|
pub error: Option<String>,
|
|
}
|
|
|
|
pub struct MCPClient {
|
|
client: Client,
|
|
server_url: String,
|
|
}
|
|
|
|
impl MCPClient {
|
|
pub fn new(server_url: &str) -> Self {
|
|
Self {
|
|
client: Client::new(),
|
|
server_url: server_url.to_string(),
|
|
}
|
|
}
|
|
|
|
pub async fn request(&self, method: &str, params: Value) -> Result<MCPResponse, Box<dyn Error>> {
|
|
let context = self.get_project_context()?;
|
|
|
|
let request = MCPRequest {
|
|
method: method.to_string(),
|
|
params,
|
|
context,
|
|
};
|
|
|
|
let response = self.client
|
|
.post(&format!("{}/execute", self.server_url))
|
|
.json(&request)
|
|
.send()
|
|
.await?
|
|
.json::<MCPResponse>()
|
|
.await?;
|
|
|
|
Ok(response)
|
|
}
|
|
|
|
pub async fn generate_code(&self, prompt: &str, language: &str) -> Result<String, Box<dyn Error>> {
|
|
let params = serde_json::json!({
|
|
"prompt": prompt,
|
|
"language": language
|
|
});
|
|
|
|
let response = self.request("code_with_local_llm", params).await?;
|
|
|
|
match response.result {
|
|
Some(result) => Ok(result["code"].as_str().unwrap_or("").to_string()),
|
|
None => Err(response.error.unwrap_or_else(|| "Unknown error".to_string()).into()),
|
|
}
|
|
}
|
|
|
|
pub async fn analyze_file(&self, file_path: &str) -> Result<String, Box<dyn Error>> {
|
|
let params = serde_json::json!({
|
|
"file_path": file_path,
|
|
"analysis_type": "general"
|
|
});
|
|
|
|
let response = self.request("read_file_with_analysis", params).await?;
|
|
|
|
match response.result {
|
|
Some(result) => Ok(result["analysis"].as_str().unwrap_or("").to_string()),
|
|
None => Err(response.error.unwrap_or_else(|| "Unknown error".to_string()).into()),
|
|
}
|
|
}
|
|
|
|
fn get_project_context(&self) -> Result<ProjectContext, Box<dyn Error>> {
|
|
use std::env;
|
|
use std::fs;
|
|
|
|
let current_dir = env::current_dir()?.to_string_lossy().to_string();
|
|
|
|
// Detect project type
|
|
let project_type = if fs::metadata("Cargo.toml").is_ok() {
|
|
Some("rust".to_string())
|
|
} else if fs::metadata("package.json").is_ok() {
|
|
Some("node".to_string())
|
|
} else if fs::metadata("requirements.txt").is_ok() || fs::metadata("setup.py").is_ok() {
|
|
Some("python".to_string())
|
|
} else {
|
|
None
|
|
};
|
|
|
|
// Get git branch
|
|
let git_branch = std::process::Command::new("git")
|
|
.args(&["branch", "--show-current"])
|
|
.output()
|
|
.ok()
|
|
.and_then(|output| {
|
|
if output.status.success() {
|
|
String::from_utf8(output.stdout).ok().map(|s| s.trim().to_string())
|
|
} else {
|
|
None
|
|
}
|
|
});
|
|
|
|
// List relevant files
|
|
let files = vec![]; // TODO: Implement file listing logic
|
|
|
|
Ok(ProjectContext {
|
|
current_dir,
|
|
project_type,
|
|
files,
|
|
git_branch,
|
|
})
|
|
}
|
|
} |