Athspi commited on
Commit
8c1a9c9
·
verified ·
1 Parent(s): 4c53399

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +206 -0
app.py ADDED
@@ -0,0 +1,206 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ # Ensure folders exist
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
+ if 'ai_understood' not in session or not session['ai_understood']:
99
+ return redirect(url_for('index'))
100
+
101
+ ai_reply = ''
102
+ if request.method == 'POST':
103
+ user_message = request.form.get('user_message')
104
+ chat_history = session.get('chat_history', [])
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
+ # Save chat history
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', []),
193
+ project_tree=session.get('project_tree', []),
194
+ ai_reply=ai_reply)
195
+
196
+ @app.route('/download_project')
197
+ def download_project():
198
+ # Zip project
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(debug=True)