1use serde::{Deserialize, Serialize};
2use std::path::PathBuf;
3use anyhow::Result;
4
5#[derive(Debug, Clone, Serialize, Deserialize)]
6pub struct SuggestionRequest {
7 pub file_path: PathBuf,
8 pub content: String,
9 pub diagnostics: Vec<String>,
10}
11
12#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct SuggestionResponse {
14 pub suggestions: Vec<AiSuggestion>,
15}
16
17#[derive(Debug, Clone, Serialize, Deserialize)]
18pub struct AiSuggestion {
19 pub title: String,
20 pub description: String,
21 pub code_snippet: Option<String>,
22 pub confidence: u8,
23}
24
25pub trait AiProvider {
26 fn name(&self) -> &str;
27 fn suggest(&self, request: SuggestionRequest) -> Result<SuggestionResponse>;
28}
29
30pub struct LocalPlaceholderProvider;
31
32impl AiProvider for LocalPlaceholderProvider {
33 fn name(&self) -> &str {
34 "local-placeholder"
35 }
36
37 fn suggest(&self, request: SuggestionRequest) -> Result<SuggestionResponse> {
38 let mut suggestions = Vec::new();
39
40 for diagnostic in &request.diagnostics {
42 if diagnostic.contains("require") {
43 suggestions.push(AiSuggestion {
44 title: "Convert to ESM Import".to_string(),
45 description: format!("Detected CommonJS pattern: '{}'. Consider migrating to ESM for better tree-shaking.", diagnostic),
46 code_snippet: Some("import name from 'source';".to_string()),
47 confidence: 90,
48 });
49 } else if diagnostic.contains("complexity") {
50 suggestions.push(AiSuggestion {
51 title: "Refactor Complex Module".to_string(),
52 description: "This module has been flagged as high complexity. Consider splitting into smaller functional components.".to_string(),
53 code_snippet: None,
54 confidence: 70,
55 });
56 }
57 }
58
59 if suggestions.is_empty() {
60 suggestions.push(AiSuggestion {
61 title: "Optimize Modernization".to_string(),
62 description: "Review this file for potential TypeScript adoption or modern ES features.".to_string(),
63 code_snippet: None,
64 confidence: 50,
65 });
66 }
67
68 Ok(SuggestionResponse { suggestions })
69 }
70}