concept_analyzer/
api.rs

1//! Simple API for one-call concept analysis
2//!
3//! This module provides a simple API interface for analyzing repositories
4//! and publishing first-principles instructions to S3.
5
6use anyhow::Result;
7#[cfg(feature = "api")]
8use axum::{
9    extract::{Json, State},
10    http::StatusCode,
11    response::IntoResponse,
12    routing::post,
13    Router,
14};
15use serde::{Deserialize, Serialize};
16use std::path::PathBuf;
17#[cfg(feature = "api")]
18use tower_http::cors::CorsLayer;
19
20use crate::unified_pipeline::analyze_repository;
21
22#[derive(Debug, Clone, Deserialize)]
23pub struct AnalyzeRequest {
24    /// Path to the repository or corpus to analyze
25    pub repo_path: String,
26    /// S3 bucket to publish results to
27    pub s3_bucket: String,
28    /// S3 key (path within bucket) for the output file
29    pub s3_key: String,
30    /// Optional number of worker threads (defaults to CPU count)
31    pub workers: Option<usize>,
32}
33
34#[derive(Debug, Clone, Serialize)]
35pub struct AnalyzeResponse {
36    /// S3 URL where the results were published
37    pub s3_url: String,
38    /// Summary of what was analyzed
39    pub summary: String,
40}
41
42#[derive(Clone)]
43pub struct ApiState {
44    llm_api_key: String,
45}
46
47#[cfg(feature = "api")]
48pub async fn create_api_router(llm_api_key: String) -> axum::Router {
49    let state = ApiState { llm_api_key };
50
51    Router::new()
52        .route("/analyze", post(analyze_handler))
53        .layer(CorsLayer::permissive())
54        .with_state(state)
55}
56
57#[cfg(feature = "api")]
58async fn analyze_handler(
59    State(state): State<ApiState>,
60    Json(request): Json<AnalyzeRequest>,
61) -> impl IntoResponse {
62    let repo_path = PathBuf::from(&request.repo_path);
63
64    if !repo_path.exists() {
65        return (
66            StatusCode::BAD_REQUEST,
67            Json(serde_json::json!({
68                "error": "Repository path does not exist"
69            })),
70        )
71            .into_response();
72    }
73
74    match analyze_repository(
75        &repo_path,
76        &request.s3_bucket,
77        &request.s3_key,
78        state.llm_api_key.clone(),
79        request.workers,
80    )
81    .await
82    {
83        Ok(s3_url) => {
84            let response = AnalyzeResponse {
85                s3_url: s3_url.clone(),
86                summary: format!(
87                    "Successfully analyzed {} and published first-principles instructions to {}",
88                    request.repo_path, s3_url
89                ),
90            };
91            (StatusCode::OK, Json(response)).into_response()
92        }
93        Err(e) => (
94            StatusCode::INTERNAL_SERVER_ERROR,
95            Json(serde_json::json!({
96                "error": format!("Analysis failed: {}", e)
97            })),
98        )
99            .into_response(),
100    }
101}
102
103// CLI entry point
104pub async fn run_cli_analysis(
105    repo_path: &str,
106    s3_bucket: &str,
107    s3_key: &str,
108    llm_api_key: &str,
109) -> Result<()> {
110    // Set up environment for demo-friendly output
111    std::env::set_var("RUST_LOG", "concept_analyzer=info");
112    env_logger::init();
113
114    println!("\nšŸŽÆ CONCEPT ANALYZER - First Principles Extractor");
115    println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
116    println!("\nThis tool will:");
117    println!("  1. Scan your repository for source files");
118    println!("  2. Extract high-level concepts using AI");
119    println!("  3. Analyze relationships between concepts");
120    println!("  4. Identify critical gaps in functionality");
121    println!("  5. Generate rebuild instructions from first principles");
122    println!("  6. Publish results to S3 for agent consumption");
123    println!("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
124
125    let s3_url = analyze_repository(
126        &PathBuf::from(repo_path),
127        s3_bucket,
128        s3_key,
129        llm_api_key.to_string(),
130        None,
131    )
132    .await?;
133
134    println!("\n\nšŸŽ‰ SUCCESS! Your first-principles blueprint is ready!");
135    println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
136    println!("\nšŸ“‹ Output Summary:");
137    println!("  āœ“ Essential concepts extracted");
138    println!("  āœ“ Core relationships mapped");
139    println!("  āœ“ Build order optimized");
140    println!("  āœ“ Critical gaps identified");
141    println!("  āœ“ Rebuild instructions generated");
142    println!("\nšŸ“ Location: {}", s3_url);
143    println!("\nšŸ’” An AI agent can now use this blueprint to:");
144    println!("  • Understand the system's core purpose");
145    println!("  • Rebuild it from scratch");
146    println!("  • Fill in the identified gaps");
147    println!("  • Maintain architectural consistency");
148    println!("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
149
150    Ok(())
151}