Update app.py
Browse files
app.py
CHANGED
@@ -1,192 +1,31 @@
|
|
|
|
1 |
import os
|
2 |
-
import zipfile
|
3 |
-
import shutil
|
4 |
-
import json
|
5 |
-
from flask import Flask, render_template, request, send_from_directory, session, redirect, url_for
|
6 |
-
import google.generativeai as genai
|
7 |
-
from werkzeug.utils import secure_filename
|
8 |
from flask_session import Session
|
9 |
-
from dotenv import load_dotenv
|
10 |
|
11 |
-
# Load .env variables
|
12 |
-
load_dotenv()
|
13 |
-
GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")
|
14 |
-
|
15 |
-
# Config Gemini
|
16 |
-
genai.configure(api_key=GEMINI_API_KEY)
|
17 |
-
model = genai.GenerativeModel('gemini-1.5-pro-latest')
|
18 |
-
|
19 |
-
# Folders
|
20 |
-
UPLOAD_FOLDER = 'uploads'
|
21 |
-
EXTRACT_FOLDER = 'uploads_extracted'
|
22 |
-
OUTPUT_FOLDER = 'outputs'
|
23 |
-
ALLOWED_EXTENSIONS = {'txt', 'pdf', 'docx', 'py', 'js', 'html', 'css', 'json', 'java', 'cpp', 'c', 'md', 'zip'}
|
24 |
-
|
25 |
-
# Flask app
|
26 |
app = Flask(__name__)
|
27 |
-
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
|
28 |
-
app.config['EXTRACT_FOLDER'] = EXTRACT_FOLDER
|
29 |
-
app.config['OUTPUT_FOLDER'] = OUTPUT_FOLDER
|
30 |
app.secret_key = 'supersecretkey'
|
31 |
app.config['SESSION_TYPE'] = 'filesystem'
|
32 |
Session(app)
|
33 |
|
34 |
-
|
35 |
-
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
|
36 |
-
os.makedirs(EXTRACT_FOLDER, exist_ok=True)
|
37 |
-
os.makedirs(OUTPUT_FOLDER, exist_ok=True)
|
38 |
-
|
39 |
-
# Helpers
|
40 |
-
def allowed_file(filename):
|
41 |
-
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
|
42 |
-
|
43 |
-
def read_file(filepath):
|
44 |
-
try:
|
45 |
-
with open(filepath, 'r', encoding='utf-8', errors='ignore') as f:
|
46 |
-
return f.read()
|
47 |
-
except Exception as e:
|
48 |
-
return f"ERROR READING FILE: {str(e)}"
|
49 |
-
|
50 |
-
def save_txt(content, filename):
|
51 |
-
filepath = os.path.join(EXTRACT_FOLDER, filename)
|
52 |
-
os.makedirs(os.path.dirname(filepath), exist_ok=True)
|
53 |
-
with open(filepath, "w", encoding="utf-8") as f:
|
54 |
-
f.write(content)
|
55 |
-
|
56 |
-
def extract_zip(zip_path, extract_to):
|
57 |
-
with zipfile.ZipFile(zip_path, 'r') as zip_ref:
|
58 |
-
zip_ref.extractall(extract_to)
|
59 |
-
|
60 |
-
def get_project_tree():
|
61 |
-
tree = []
|
62 |
-
for root, dirs, files in os.walk(EXTRACT_FOLDER):
|
63 |
-
for name in files:
|
64 |
-
rel_path = os.path.relpath(os.path.join(root, name), EXTRACT_FOLDER)
|
65 |
-
tree.append(rel_path)
|
66 |
-
return tree
|
67 |
-
|
68 |
-
# Routes
|
69 |
-
@app.route('/', methods=['GET', 'POST'])
|
70 |
def index():
|
71 |
-
if request.method == 'POST':
|
72 |
-
# Clear previous project
|
73 |
-
shutil.rmtree(EXTRACT_FOLDER)
|
74 |
-
os.makedirs(EXTRACT_FOLDER)
|
75 |
-
|
76 |
-
files = request.files.getlist('files')
|
77 |
-
for file in files:
|
78 |
-
if file and allowed_file(file.filename):
|
79 |
-
filename = secure_filename(file.filename)
|
80 |
-
filepath = os.path.join(UPLOAD_FOLDER, filename)
|
81 |
-
file.save(filepath)
|
82 |
-
|
83 |
-
if filename.endswith('.zip'):
|
84 |
-
extract_zip(filepath, EXTRACT_FOLDER)
|
85 |
-
else:
|
86 |
-
save_txt(read_file(filepath), filename)
|
87 |
-
|
88 |
-
session['chat_history'] = []
|
89 |
-
session['ai_understood'] = True
|
90 |
-
session['project_tree'] = get_project_tree()
|
91 |
-
|
92 |
-
return redirect(url_for('chat'))
|
93 |
-
|
94 |
return render_template('index.html')
|
95 |
|
96 |
@app.route('/chat', methods=['GET', 'POST'])
|
97 |
def chat():
|
98 |
-
|
99 |
-
|
|
|
|
|
|
|
|
|
100 |
|
101 |
ai_reply = ''
|
102 |
if request.method == 'POST':
|
103 |
user_message = request.form.get('user_message')
|
104 |
-
|
105 |
-
|
106 |
-
# Build project context
|
107 |
-
all_text = ''
|
108 |
-
for file_path in get_project_tree():
|
109 |
-
full_path = os.path.join(EXTRACT_FOLDER, file_path)
|
110 |
-
content = read_file(full_path)
|
111 |
-
all_text += f"\n--- File: {file_path} ---\n{content}\n"
|
112 |
-
|
113 |
-
# Build chat prompt
|
114 |
-
chat_prompt = ''
|
115 |
-
for chat in chat_history:
|
116 |
-
chat_prompt += f"User: {chat['user']}\nAI: {chat['ai']}\n"
|
117 |
-
|
118 |
-
full_prompt = f"""
|
119 |
-
You are an expert AI project code editor.
|
120 |
-
The user uploaded this project:
|
121 |
-
|
122 |
-
{all_text}
|
123 |
-
|
124 |
-
Chat history:
|
125 |
-
{chat_prompt}
|
126 |
-
|
127 |
-
Now user says:
|
128 |
-
{user_message}
|
129 |
-
|
130 |
-
Please reply with:
|
131 |
-
- what files you edited (if any)
|
132 |
-
- content of new/edited files
|
133 |
-
- if user says DELETE file, remove it
|
134 |
-
- reply in readable format.
|
135 |
-
|
136 |
-
Example format:
|
137 |
-
|
138 |
-
### Edited Files:
|
139 |
-
File: filename.py
|
140 |
-
Content:
|
141 |
-
<content here>
|
142 |
-
|
143 |
-
### New Files:
|
144 |
-
File: newfile.py
|
145 |
-
Content:
|
146 |
-
<content here>
|
147 |
-
|
148 |
-
### Deleted Files:
|
149 |
-
filename1
|
150 |
-
filename2
|
151 |
-
|
152 |
-
### Notes:
|
153 |
-
<summary notes here>
|
154 |
-
"""
|
155 |
-
|
156 |
-
# Run Gemini API
|
157 |
-
response = model.generate_content(full_prompt)
|
158 |
-
ai_reply = response.text
|
159 |
-
|
160 |
-
# Parse AI reply to save files
|
161 |
-
if "### New Files:" in ai_reply:
|
162 |
-
parts = ai_reply.split("### New Files:")[-1].split("###")[0].strip().split("File:")
|
163 |
-
for part in parts[1:]:
|
164 |
-
lines = part.strip().split("\n")
|
165 |
-
filename = lines[0].strip()
|
166 |
-
content = "\n".join(lines[2:]).strip()
|
167 |
-
save_txt(content, filename)
|
168 |
-
|
169 |
-
if "### Edited Files:" in ai_reply:
|
170 |
-
parts = ai_reply.split("### Edited Files:")[-1].split("###")[0].strip().split("File:")
|
171 |
-
for part in parts[1:]:
|
172 |
-
lines = part.strip().split("\n")
|
173 |
-
filename = lines[0].strip()
|
174 |
-
content = "\n".join(lines[2:]).strip()
|
175 |
-
save_txt(content, filename)
|
176 |
-
|
177 |
-
if "### Deleted Files:" in ai_reply:
|
178 |
-
parts = ai_reply.split("### Deleted Files:")[-1].split("###")[0].strip().split("\n")
|
179 |
-
for filename in parts:
|
180 |
-
filename = filename.strip()
|
181 |
-
if filename:
|
182 |
-
path_to_delete = os.path.join(EXTRACT_FOLDER, filename)
|
183 |
-
if os.path.exists(path_to_delete):
|
184 |
-
os.remove(path_to_delete)
|
185 |
|
186 |
-
|
187 |
-
chat_history.append({'user': user_message, 'ai': ai_reply})
|
188 |
-
session['chat_history'] = chat_history
|
189 |
-
session['project_tree'] = get_project_tree()
|
190 |
|
191 |
return render_template('chat.html',
|
192 |
chat_history=session.get('chat_history', []),
|
@@ -195,12 +34,7 @@ filename2
|
|
195 |
|
196 |
@app.route('/download_project')
|
197 |
def download_project():
|
198 |
-
|
199 |
-
zip_filename = 'project.zip'
|
200 |
-
zip_path = os.path.join(OUTPUT_FOLDER, zip_filename)
|
201 |
-
shutil.make_archive(os.path.splitext(zip_path)[0], 'zip', EXTRACT_FOLDER)
|
202 |
-
return send_from_directory(OUTPUT_FOLDER, zip_filename, as_attachment=True)
|
203 |
|
204 |
-
# Run app
|
205 |
if __name__ == '__main__':
|
206 |
-
app.run(
|
|
|
1 |
+
from flask import Flask, render_template, request, session, redirect, url_for
|
2 |
import os
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
from flask_session import Session
|
|
|
4 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
app = Flask(__name__)
|
|
|
|
|
|
|
6 |
app.secret_key = 'supersecretkey'
|
7 |
app.config['SESSION_TYPE'] = 'filesystem'
|
8 |
Session(app)
|
9 |
|
10 |
+
@app.route('/')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
def index():
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
return render_template('index.html')
|
13 |
|
14 |
@app.route('/chat', methods=['GET', 'POST'])
|
15 |
def chat():
|
16 |
+
# Simulate chat history
|
17 |
+
if 'chat_history' not in session:
|
18 |
+
session['chat_history'] = []
|
19 |
+
|
20 |
+
if 'project_tree' not in session:
|
21 |
+
session['project_tree'] = ['main.py', 'requirements.txt', 'templates/index.html']
|
22 |
|
23 |
ai_reply = ''
|
24 |
if request.method == 'POST':
|
25 |
user_message = request.form.get('user_message')
|
26 |
+
ai_reply = "Simulated AI response to: " + user_message
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
|
28 |
+
session['chat_history'].append({'user': user_message, 'ai': ai_reply})
|
|
|
|
|
|
|
29 |
|
30 |
return render_template('chat.html',
|
31 |
chat_history=session.get('chat_history', []),
|
|
|
34 |
|
35 |
@app.route('/download_project')
|
36 |
def download_project():
|
37 |
+
return "Simulated download"
|
|
|
|
|
|
|
|
|
38 |
|
|
|
39 |
if __name__ == '__main__':
|
40 |
+
app.run(debug=True)
|