import os
import shutil
import tempfile
from flask import Flask, request, jsonify, render_template_string
import git
import json
import google.generativeai as genai
import traceback
# --- Configure API Key ---
API_KEY = os.environ.get("GOOGLE_API_KEY")
if API_KEY:
try:
genai.configure(api_key=API_KEY)
print("✅ Google API Key configured successfully.")
except Exception as e:
print(f"🚨 ERROR: Failed to configure Google API Key. Error: {e}")
else:
print("🚨 WARNING: GOOGLE_API_KEY secret not set in Hugging Face Spaces.")
app = Flask(__name__)
HTML_TEMPLATE = """
AI README Generator 🧠
AI README Generator 🧠
Enter a public GitHub repository URL and let a true AI agent analyze the code and generate a README for you.
Generated README.md:
"""
def generate_readme_with_llm(repo_path):
print("Step 4: Starting to analyze repository files.")
file_structure = ""
file_contents = ""
for root, _, files in os.walk(repo_path):
if '.git' in root:
continue
level = root.replace(repo_path, '').count(os.sep)
indent = ' ' * 4 * level
file_structure += f"{indent}{os.path.basename(root)}/\n"
sub_indent = ' ' * 4 * (level + 1)
for f in files[:5]:
file_structure += f"{sub_indent}{f}\n"
try:
with open(os.path.join(root, f), 'r', errors='ignore') as file:
content = file.read(2000)
file_contents += f"\n--- Start of {f} ---\n{content}\n--- End of {f} ---\n"
except Exception:
continue
prompt = f"""
You are an expert technical writer. Analyze the repository context below and generate a professional README.md.
**File Structure:**
```
{file_structure}
```
**Key File Contents:**
```
{file_contents}
```
Generate a README.md with these sections: Project Title, About the Project, Getting Started, and Usage.
- Infer purpose, technologies, and setup commands.
- Output must be valid Markdown.
"""
try:
print("Step 5: Sending request to Gemini API...")
# Reverted model name back to user's preference.
model = genai.GenerativeModel('gemini-2.5-flash')
response = model.generate_content(prompt)
print("Step 6: Received response from Gemini API.")
readme_text = response.text.strip().replace("```markdown", "").replace("```", "")
return readme_text
except Exception as e:
print(f"🚨🚨🚨 CRITICAL ERROR during Gemini API call: {e}")
raise
@app.route('/')
def index():
return render_template_string(HTML_TEMPLATE)
@app.route('/generate', methods=['POST'])
def generate():
print("\n--- NEW REQUEST ---")
print("Step 1: Received request to /generate.")
data = request.get_json()
if not data or 'url' not in data:
return jsonify({"error": "Request body must be JSON with a 'url' key."}), 400
repo_url = data.get('url')
if not repo_url or "github.com" not in repo_url.lower():
print(f"Validation failed for URL: {repo_url}")
return jsonify({"error": "A valid public GitHub repository URL is required."}), 400
if not API_KEY:
return jsonify({"error": "Server is missing the GOOGLE_API_KEY. Cannot contact the LLM."}), 500
temp_dir = tempfile.mkdtemp()
try:
print(f"Step 2: Cloning repository: {repo_url} into {temp_dir}")
git.Repo.clone_from(repo_url, temp_dir)
print("Step 3: Cloning successful.")
readme_content = generate_readme_with_llm(temp_dir)
print("Step 7: Successfully generated README. Sending response.")
return jsonify({"readme": readme_content})
except Exception as e:
print(f"🚨🚨🚨 AN UNEXPECTED ERROR OCCURRED in /generate route 🚨🚨🚨")
traceback.print_exc()
return jsonify({"error": "An unexpected server error occurred. Please check the logs."}), 500
finally:
print(f"Step 8: Cleaning up temporary directory: {temp_dir}")
shutil.rmtree(temp_dir)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=int(os.environ.get("PORT", 7860)))