use anyhow::Result;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::path::Path;
use crate::{
types::code::{CodePurpose, CodePurposeMapper},
};
use crate::generator::agent_executor::{AgentExecuteParams, extract};
use crate::generator::context::GeneratorContext;
#[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)]
pub struct AICodePurposeAnalysis {
pub code_purpose: CodePurpose,
pub confidence: f64,
pub reasoning: String,
}
pub struct CodePurposeEnhancer;
impl CodePurposeEnhancer {
pub fn new() -> Self {
Self {}
}
pub async fn execute(
&self,
context: &GeneratorContext,
file_path: &Path,
file_name: &str,
file_content: &str) -> Result<CodePurpose>
{
let rule_based_type =
CodePurposeMapper::map_by_path_and_name(&file_path.to_string_lossy(), file_name);
if rule_based_type != CodePurpose::Other {
return Ok(rule_based_type);
}
let prompt_sys = "You are a professional code architecture analyst specializing in analyzing component types of code files.".to_string();
let prompt_user = self.build_code_purpose_analysis_prompt(file_path, file_content, file_name);
let analyze_result = extract::<AICodePurposeAnalysis>(context, AgentExecuteParams {
prompt_sys,
prompt_user,
cache_scope: "ai_code_purpose".to_string(),
log_tag: file_name.to_string(),
}).await;
return match analyze_result {
Ok(ai_analysis) => {
if ai_analysis.confidence > 0.7 {
return Ok(ai_analysis.code_purpose);
}
if rule_based_type != CodePurpose::Other {
Ok(rule_based_type)
} else {
Ok(ai_analysis.code_purpose)
}
}
Err(_) => {
Ok(rule_based_type)
}
}
}
fn build_code_purpose_analysis_prompt(
&self,
file_path: &Path,
file_content: &str,
file_name: &str,
) -> String {
let content_preview = if file_content.chars().count() > 1000 {
let truncated: String = file_content.chars().take(1000).collect();
format!("{}...", truncated)
} else {
file_content.to_string()
};
format!(
include_str!("prompts/code_purpose_analyze_user.tpl"),
file_path.display(),
file_name,
content_preview
)
}
}