Athspi commited on
Commit
2a5fc68
·
verified ·
1 Parent(s): 3e0f161

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +32 -27
app.py CHANGED
@@ -6,19 +6,20 @@ from flask import Flask, request, jsonify, render_template, session, send_from_d
6
  from flask_session import Session
7
  from dotenv import load_dotenv
8
 
9
- # --- API and App Configuration ---
10
  load_dotenv()
11
 
 
12
  app = Flask(__name__)
13
  app.config["SECRET_KEY"] = os.environ.get("FLASK_SECRET_KEY", 'default-insecure-secret-key')
14
 
15
- # --- SERVER-SIDE SESSION CONFIGURATION ---
16
  app.config["SESSION_PERMANENT"] = False
17
  app.config["SESSION_TYPE"] = "filesystem"
18
  app.config['SESSION_FILE_DIR'] = './flask_session'
19
  Session(app)
20
 
21
- # Configure the Gemini API client
22
  try:
23
  gemini_api_key = os.environ.get("GEMINI_API_KEY")
24
  if not gemini_api_key:
@@ -26,24 +27,24 @@ try:
26
  model = None
27
  else:
28
  genai.configure(api_key=gemini_api_key)
29
- model = genai.GenerativeModel('gemini-2.0-flash')
30
  except Exception as e:
31
  print(f"Error configuring Gemini API: {e}")
32
  model = None
33
 
34
- # Configure the upload folder
35
  UPLOAD_FOLDER = 'uploads'
36
  app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
37
- if not os.path.exists(UPLOAD_FOLDER):
38
- os.makedirs(UPLOAD_FOLDER)
39
- if not os.path.exists('./flask_session'):
40
- os.makedirs('./flask_session')
41
 
42
  def get_project_files(project_path):
 
43
  file_data = {}
44
  for root, _, files in os.walk(project_path):
45
  for file in files:
46
- if file in ['.DS_Store', '__MACOSX']: continue
 
47
  file_path = os.path.join(root, file)
48
  relative_path = os.path.relpath(file_path, project_path)
49
  try:
@@ -56,6 +57,7 @@ def get_project_files(project_path):
56
 
57
  @app.route('/')
58
  def index():
 
59
  if 'project_id' not in session:
60
  session['project_id'] = str(uuid.uuid4())
61
  session['chat_history'] = []
@@ -63,6 +65,7 @@ def index():
63
 
64
  @app.route('/upload', methods=['POST'])
65
  def upload_project():
 
66
  if 'project_id' not in session:
67
  session['project_id'] = str(uuid.uuid4())
68
  session['chat_history'] = []
@@ -78,7 +81,7 @@ def upload_project():
78
  project_id = session['project_id']
79
  project_path = os.path.join(app.config['UPLOAD_FOLDER'], project_id)
80
 
81
- # Clear existing project files if they exist
82
  if os.path.exists(project_path):
83
  for root, dirs, files in os.walk(project_path, topdown=False):
84
  for name in files:
@@ -96,30 +99,32 @@ def upload_project():
96
 
97
  project_files = get_project_files(project_path)
98
 
 
99
  initial_context = "The user has uploaded a new project. Here is the file structure and content:\n\n"
100
  for path, content in project_files.items():
101
  initial_context += f"**File:** `{path}`\n```\n{content}\n```\n\n"
102
 
 
103
  session['chat_history'] = [
104
  {"role": "user", "parts": [initial_context]},
105
  {"role": "model", "parts": ["I have analyzed the project. I am ready to help. How can I assist you with your code?"]}
106
  ]
107
  session.modified = True
108
 
109
- frontend_chat_history = [
110
- {"role": "user", "content": "Project context sent to AI."},
111
- {"role": "assistant", "content": "I have analyzed the project. I am ready to help. How can I assist you with your code?"}
112
- ]
113
-
114
  return jsonify({
115
  "message": "Project uploaded and analyzed.",
116
  "file_tree": list(project_files.keys()),
117
- "chat_history": frontend_chat_history
 
 
 
118
  })
119
  return jsonify({"error": "Invalid file type. Please upload a .zip file."}), 400
120
 
121
  @app.route('/chat', methods=['POST'])
122
  def chat():
 
123
  if not model:
124
  return jsonify({"error": "Gemini API is not configured. Please check your API key."}), 500
125
 
@@ -129,7 +134,7 @@ def chat():
129
 
130
  project_id = session.get('project_id')
131
  if not project_id:
132
- return jsonify({"error": "Your session has expired or could not be found. Please upload your project again."}), 400
133
 
134
  project_path = os.path.join(app.config['UPLOAD_FOLDER'], project_id)
135
  session['chat_history'].append({"role": "user", "parts": [user_message]})
@@ -157,7 +162,7 @@ def chat():
157
  os.makedirs(os.path.dirname(full_path), exist_ok=True)
158
  with open(full_path, 'w', encoding='utf-8') as f:
159
  f.write(code_content)
160
- except IndexError:
161
  pass
162
  elif ai_response.strip().startswith("DELETE:"):
163
  file_to_delete = ai_response.strip().split(":", 1)[1].strip()
@@ -174,9 +179,10 @@ def chat():
174
 
175
  @app.route('/file_tree')
176
  def get_file_tree():
 
177
  project_id = session.get('project_id')
178
  if not project_id:
179
- return jsonify({"error": "No project in session. Please upload a project first."}), 400
180
 
181
  project_path = os.path.join(app.config['UPLOAD_FOLDER'], project_id)
182
  if not os.path.exists(project_path):
@@ -186,17 +192,16 @@ def get_file_tree():
186
  project_files = get_project_files(project_path)
187
  return jsonify({"file_tree": list(project_files.keys())})
188
  except Exception as e:
189
- return jsonify({"error": str(e)}), 500
190
 
191
  @app.route('/file_content')
192
  def get_file_content():
 
193
  project_id = session.get('project_id')
194
  file_path = request.args.get('path')
195
 
196
- if not project_id:
197
- return jsonify({"error": "No project in session. Please upload a project first."}), 400
198
- if not file_path:
199
- return jsonify({"error": "Missing file path"}), 400
200
 
201
  full_path = os.path.join(app.config['UPLOAD_FOLDER'], project_id, file_path)
202
  if not os.path.exists(full_path):
@@ -211,6 +216,7 @@ def get_file_content():
211
 
212
  @app.route('/download')
213
  def download_project():
 
214
  project_id = session.get('project_id')
215
  if not project_id:
216
  return "No project to download. Please upload a project first.", 404
@@ -222,7 +228,6 @@ def download_project():
222
  zip_filename = f"project_{project_id}.zip"
223
  zip_path = os.path.join(app.config['UPLOAD_FOLDER'], zip_filename)
224
 
225
- # Remove existing zip if it exists
226
  if os.path.exists(zip_path):
227
  os.remove(zip_path)
228
 
@@ -236,4 +241,4 @@ def download_project():
236
  return send_from_directory(app.config['UPLOAD_FOLDER'], zip_filename, as_attachment=True)
237
 
238
  if __name__ == '__main__':
239
- app.run(host="0.0.0.0", port=7860)
 
6
  from flask_session import Session
7
  from dotenv import load_dotenv
8
 
9
+ # Load environment variables
10
  load_dotenv()
11
 
12
+ # Initialize Flask app
13
  app = Flask(__name__)
14
  app.config["SECRET_KEY"] = os.environ.get("FLASK_SECRET_KEY", 'default-insecure-secret-key')
15
 
16
+ # Configure server-side sessions
17
  app.config["SESSION_PERMANENT"] = False
18
  app.config["SESSION_TYPE"] = "filesystem"
19
  app.config['SESSION_FILE_DIR'] = './flask_session'
20
  Session(app)
21
 
22
+ # Configure Gemini AI
23
  try:
24
  gemini_api_key = os.environ.get("GEMINI_API_KEY")
25
  if not gemini_api_key:
 
27
  model = None
28
  else:
29
  genai.configure(api_key=gemini_api_key)
30
+ model = genai.GenerativeModel('gemini-1.5-flash')
31
  except Exception as e:
32
  print(f"Error configuring Gemini API: {e}")
33
  model = None
34
 
35
+ # Configure upload folder
36
  UPLOAD_FOLDER = 'uploads'
37
  app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
38
+ os.makedirs(UPLOAD_FOLDER, exist_ok=True)
39
+ os.makedirs('./flask_session', exist_ok=True)
 
 
40
 
41
  def get_project_files(project_path):
42
+ """Get all files in a project directory with their contents."""
43
  file_data = {}
44
  for root, _, files in os.walk(project_path):
45
  for file in files:
46
+ if file in ['.DS_Store', '__MACOSX']:
47
+ continue
48
  file_path = os.path.join(root, file)
49
  relative_path = os.path.relpath(file_path, project_path)
50
  try:
 
57
 
58
  @app.route('/')
59
  def index():
60
+ """Render the main application page."""
61
  if 'project_id' not in session:
62
  session['project_id'] = str(uuid.uuid4())
63
  session['chat_history'] = []
 
65
 
66
  @app.route('/upload', methods=['POST'])
67
  def upload_project():
68
+ """Handle project zip file upload."""
69
  if 'project_id' not in session:
70
  session['project_id'] = str(uuid.uuid4())
71
  session['chat_history'] = []
 
81
  project_id = session['project_id']
82
  project_path = os.path.join(app.config['UPLOAD_FOLDER'], project_id)
83
 
84
+ # Clear existing project files
85
  if os.path.exists(project_path):
86
  for root, dirs, files in os.walk(project_path, topdown=False):
87
  for name in files:
 
99
 
100
  project_files = get_project_files(project_path)
101
 
102
+ # Prepare initial context for AI
103
  initial_context = "The user has uploaded a new project. Here is the file structure and content:\n\n"
104
  for path, content in project_files.items():
105
  initial_context += f"**File:** `{path}`\n```\n{content}\n```\n\n"
106
 
107
+ # Update session with chat history
108
  session['chat_history'] = [
109
  {"role": "user", "parts": [initial_context]},
110
  {"role": "model", "parts": ["I have analyzed the project. I am ready to help. How can I assist you with your code?"]}
111
  ]
112
  session.modified = True
113
 
114
+ # Prepare response for frontend
 
 
 
 
115
  return jsonify({
116
  "message": "Project uploaded and analyzed.",
117
  "file_tree": list(project_files.keys()),
118
+ "chat_history": [
119
+ {"role": "user", "content": "Project context sent to AI."},
120
+ {"role": "assistant", "content": "I have analyzed the project. I am ready to help. How can I assist you with your code?"}
121
+ ]
122
  })
123
  return jsonify({"error": "Invalid file type. Please upload a .zip file."}), 400
124
 
125
  @app.route('/chat', methods=['POST'])
126
  def chat():
127
+ """Handle chat messages with the AI."""
128
  if not model:
129
  return jsonify({"error": "Gemini API is not configured. Please check your API key."}), 500
130
 
 
134
 
135
  project_id = session.get('project_id')
136
  if not project_id:
137
+ return jsonify({"error": "Session expired. Please upload your project again."}), 400
138
 
139
  project_path = os.path.join(app.config['UPLOAD_FOLDER'], project_id)
140
  session['chat_history'].append({"role": "user", "parts": [user_message]})
 
162
  os.makedirs(os.path.dirname(full_path), exist_ok=True)
163
  with open(full_path, 'w', encoding='utf-8') as f:
164
  f.write(code_content)
165
+ except Exception:
166
  pass
167
  elif ai_response.strip().startswith("DELETE:"):
168
  file_to_delete = ai_response.strip().split(":", 1)[1].strip()
 
179
 
180
  @app.route('/file_tree')
181
  def get_file_tree():
182
+ """Get the current project's file tree."""
183
  project_id = session.get('project_id')
184
  if not project_id:
185
+ return jsonify({"file_tree": []})
186
 
187
  project_path = os.path.join(app.config['UPLOAD_FOLDER'], project_id)
188
  if not os.path.exists(project_path):
 
192
  project_files = get_project_files(project_path)
193
  return jsonify({"file_tree": list(project_files.keys())})
194
  except Exception as e:
195
+ return jsonify({"file_tree": []})
196
 
197
  @app.route('/file_content')
198
  def get_file_content():
199
+ """Get the content of a specific file."""
200
  project_id = session.get('project_id')
201
  file_path = request.args.get('path')
202
 
203
+ if not project_id or not file_path:
204
+ return jsonify({"error": "No file selected"}), 400
 
 
205
 
206
  full_path = os.path.join(app.config['UPLOAD_FOLDER'], project_id, file_path)
207
  if not os.path.exists(full_path):
 
216
 
217
  @app.route('/download')
218
  def download_project():
219
+ """Download the current project as a zip file."""
220
  project_id = session.get('project_id')
221
  if not project_id:
222
  return "No project to download. Please upload a project first.", 404
 
228
  zip_filename = f"project_{project_id}.zip"
229
  zip_path = os.path.join(app.config['UPLOAD_FOLDER'], zip_filename)
230
 
 
231
  if os.path.exists(zip_path):
232
  os.remove(zip_path)
233
 
 
241
  return send_from_directory(app.config['UPLOAD_FOLDER'], zip_filename, as_attachment=True)
242
 
243
  if __name__ == '__main__':
244
+ app.run(host="0.0.0.0", port=7860, debug=True)