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)