morph-cli 0.1.0

AST-based codebase migration and codemod tool for JavaScript and TypeScript projects.
Documentation
use std::path::Path;
use anyhow::{Result, Context, bail};
use indicatif::ProgressBar;
use crate::core::ai::{AiProvider, LocalPlaceholderProvider, SuggestionRequest};
use crate::core::registry::RecipeRegistry;
use crate::utils::terminal;
use colored::Colorize;

pub fn suggest(path: &Path) -> Result<()> {
    if !path.exists() {
        bail!("File does not exist: {}", path.display());
    }

    let spinner = terminal::spinner(format!("Analyzing {} for AI suggestions...", path.display()).as_str());

    let registry = RecipeRegistry::new();
    let progress = ProgressBar::hidden();
    let mut diagnostics = Vec::new();

    // Gather diagnostics from all recipes (reusing explain logic)
    for recipe in registry.all() {
        if let Ok(report) = recipe.detect(path, &progress) {
            if let Some(analysis) = report.analyses.iter().find(|a| a.path == path) {
                diagnostics.extend(analysis.detected_patterns.clone());
            }
        }
    }

    let content = std::fs::read_to_string(path).context("Failed to read file content")?;
    let request = SuggestionRequest {
        file_path: path.to_path_buf(),
        content,
        diagnostics,
    };

    let provider = LocalPlaceholderProvider;
    let response = provider.suggest(request)?;

    spinner.finish_and_clear();

    println!();
    println!("{} AI Suggestions for: {}", terminal::success_prefix(), terminal::label(path.display().to_string().as_str()));
    println!("{}", "".repeat(50));

    if response.suggestions.is_empty() {
        println!("  No specific suggestions found for this file.");
    } else {
        for suggestion in response.suggestions {
            println!("\n  {} {}", terminal::bullet(), terminal::label(&suggestion.title));
            println!("    {}", suggestion.description);
            println!("    Confidence: {}%", suggestion.confidence);
            if let Some(snippet) = suggestion.code_snippet {
                println!("\n    Recommended Change:");
                for line in snippet.lines() {
                    println!("      {}", line.dimmed());
                }
            }
        }
    }
    println!();

    Ok(())
}