File size: 5,135 Bytes
8c1a9c9 9759c17 001d634 3e0f161 9759c17 8b2be7b 9759c17 8b2be7b ea92302 9759c17 61bb0ed 8b2be7b 3e0f161 8b2be7b 3e0f161 d9e48e0 9759c17 2a5fc68 8b2be7b 9759c17 8b2be7b 9759c17 8b2be7b 9759c17 8b2be7b 8c1a9c9 8a7ffa1 8c1a9c9 9759c17 8c1a9c9 9759c17 8b2be7b 8c4ce97 8b2be7b 9759c17 8b2be7b 9759c17 8b2be7b d9e48e0 9759c17 8c1a9c9 8c4ce97 8b2be7b 8c4ce97 8b2be7b 9759c17 8b2be7b 8c4ce97 9759c17 8b2be7b 2a5fc68 8b2be7b 8c4ce97 9759c17 8b2be7b 9759c17 8b2be7b 8c4ce97 8b2be7b 8c4ce97 9759c17 8b2be7b 9759c17 8b2be7b |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
import os
import zipfile
import uuid
from flask import Flask, request, jsonify, render_template, session, send_from_directory
from flask_session import Session
from dotenv import load_dotenv
import google.generativeai as genai
# Load env
load_dotenv()
app = Flask(__name__)
app.config["SECRET_KEY"] = os.getenv("FLASK_SECRET_KEY", "insecure")
app.config["SESSION_TYPE"] = "filesystem"
app.config["SESSION_FILE_DIR"] = './flask_session'
app.config["SESSION_PERMANENT"] = False
Session(app)
UPLOAD_FOLDER = 'uploads'
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
os.makedirs(app.config['SESSION_FILE_DIR'], exist_ok=True)
# Configure Gemini
gemini_api_key = os.getenv("GEMINI_API_KEY")
model = None
if gemini_api_key:
genai.configure(api_key=gemini_api_key)
model = genai.GenerativeModel('gemini-2.0-flash')
def get_project_files(project_path):
files = {}
for root, _, filenames in os.walk(project_path):
for file in filenames:
if file.startswith('.'): continue
rel_path = os.path.relpath(os.path.join(root, file), project_path)
try:
with open(os.path.join(root, file), 'r', encoding='utf-8', errors='ignore') as f:
files[rel_path] = f.read()
except Exception as e:
files[rel_path] = f"Error reading: {e}"
return files
@app.route('/')
def index():
if 'project_id' not in session:
session['project_id'] = str(uuid.uuid4())
session['chat_history'] = []
return render_template('index.html')
@app.route('/upload', methods=['POST'])
def upload():
if 'project_zip' not in request.files:
return jsonify({'error': 'No file uploaded'}), 400
file = request.files['project_zip']
if not file.filename.endswith('.zip'):
return jsonify({'error': 'Only .zip supported'}), 400
project_id = session['project_id']
project_path = os.path.join(app.config['UPLOAD_FOLDER'], project_id)
if os.path.exists(project_path):
for root, dirs, files in os.walk(project_path, topdown=False):
for f in files:
os.remove(os.path.join(root, f))
for d in dirs:
os.rmdir(os.path.join(root, d))
os.makedirs(project_path, exist_ok=True)
zip_path = os.path.join(project_path, file.filename)
file.save(zip_path)
with zipfile.ZipFile(zip_path, 'r') as z:
z.extractall(project_path)
os.remove(zip_path)
files = get_project_files(project_path)
context = "User uploaded a project:\n"
for path, content in files.items():
context += f"**File:** `{path}`\n```\n{content[:2000]}\n```\n\n" # clip long content
session['chat_history'] = [
{"role": "user", "parts": [context]},
{"role": "model", "parts": ["Project loaded. Ready to help."]}
]
session.modified = True
return jsonify({
"message": "Project uploaded.",
"file_tree": list(files.keys()),
"chat_history": [
{"role": "user", "content": "Project context sent to AI."},
{"role": "assistant", "content": "Project loaded. Ready to help."}
]
})
@app.route('/chat', methods=['POST'])
def chat():
if not model:
return jsonify({"error": "Gemini API not configured"}), 500
msg = request.json.get("message")
if not msg:
return jsonify({"error": "Empty message"}), 400
session['chat_history'].append({"role": "user", "parts": [msg]})
try:
chat = model.start_chat(history=session['chat_history'])
reply = chat.send_message(msg).text
session['chat_history'].append({"role": "model", "parts": [reply]})
return jsonify({"reply": reply})
except Exception as e:
return jsonify({"error": str(e)}), 500
@app.route('/file_tree')
def file_tree():
pid = session.get('project_id')
if not pid:
return jsonify({"file_tree": []})
path = os.path.join(app.config['UPLOAD_FOLDER'], pid)
return jsonify({"file_tree": list(get_project_files(path).keys())})
@app.route('/file_content')
def file_content():
pid = session.get('project_id')
filepath = request.args.get('path')
full = os.path.join(app.config['UPLOAD_FOLDER'], pid, filepath)
try:
with open(full, 'r', encoding='utf-8', errors='ignore') as f:
return jsonify({"content": f.read()})
except Exception as e:
return jsonify({"error": str(e)})
@app.route('/download')
def download():
pid = session.get('project_id')
if not pid:
return "No project uploaded", 404
path = os.path.join(app.config['UPLOAD_FOLDER'], pid)
zpath = os.path.join(app.config['UPLOAD_FOLDER'], f"{pid}.zip")
with zipfile.ZipFile(zpath, 'w') as zipf:
for root, _, files in os.walk(path):
for file in files:
fpath = os.path.join(root, file)
zipf.write(fpath, os.path.relpath(fpath, path))
return send_from_directory(app.config['UPLOAD_FOLDER'], f"{pid}.zip", as_attachment=True)
if __name__ == "__main__":
app.run(host='0.0.0.0', port=7860)
|