import os
import shutil
import tempfile
from flask import Flask, request, jsonify, render_template_string
import git
import json
import google.generativeai as genai
# --- IMPORTANT: Configure your API Key ---
try:
genai.configure(api_key=os.environ.get("GOOGLE_API_KEY"))
except AttributeError:
print("WARNING: GOOGLE_API_KEY secret not set. LLM functionality will fail.")
# Create the Flask app instance
app = Flask(__name__)
# The HTML template remains the same
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.
"""
def generate_readme_with_llm(repo_path):
"""
Analyzes the repo and uses an LLM to generate the README content.
"""
file_structure = ""
file_contents = ""
file_limit = 5
char_limit_per_file = 2000
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[:file_limit]:
file_structure += f"{sub_indent}{f}\n"
try:
with open(os.path.join(root, f), 'r', errors='ignore') as file:
content = file.read(char_limit_per_file)
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 tasked with creating a high-quality README.md for a GitHub repository.
Analyze the following repository context and generate a comprehensive and user-friendly README.
**Repository Context:**
**1. File Structure:**
```
{file_structure}
```
**2. Content of Key Files:**
```
{file_contents}
```
**Instructions:**
Generate a README.md with these sections: Project Title, About the Project, Getting Started, and Usage.
- Infer the project purpose, technologies, and setup commands from the files.
- The output must be valid Markdown.
- If a command is unknown, suggest a common default (e.g., `npm install`).
"""
print("Sending request to Gemini API...")
model = genai.GenerativeModel('gemini-1.5-flash-latest')
response = model.generate_content(prompt)
readme_text = response.text.strip()
if readme_text.startswith("```markdown"):
readme_text = readme_text[10:]
if readme_text.endswith("```"):
readme_text = readme_text[:-3]
return readme_text
@app.route('/')
def index():
return render_template_string(HTML_TEMPLATE)
@app.route('/generate', methods=['POST'])
def 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')
# --- BUG FIX: Make URL validation more flexible ---
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 os.environ.get("GOOGLE_API_KEY"):
return jsonify({"error": "Server is missing the GOOGLE_API_KEY. Cannot contact the LLM."}), 500
temp_dir = tempfile.mkdtemp()
try:
print(f"Cloning repository: {repo_url} into {temp_dir}")
git.Repo.clone_from(repo_url, temp_dir)
print("Cloning successful.")
readme_content = generate_readme_with_llm(temp_dir)
return jsonify({"readme": readme_content})
except git.exc.GitCommandError as e:
error_message = str(e).lower()
print(f"Git error: {error_message}")
if "authentication failed" in error_message or "not found" in error_message:
return jsonify({"error": "Failed to clone. Please ensure the URL is correct and the repository is public."}), 400
else:
return jsonify({"error": f"A Git error occurred during cloning."}), 500
except Exception as e:
print(f"An unexpected error occurred: {e}")
return jsonify({"error": f"An unexpected error occurred on the server."}), 500
finally:
print(f"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)))