WebashalarForML commited on
Commit
840ea23
·
verified ·
1 Parent(s): d8bbc7e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +395 -395
app.py CHANGED
@@ -1,395 +1,395 @@
1
- """Main application entry point for the multi-language chat agent."""
2
-
3
- import os
4
- from flask import Flask
5
- from flask_socketio import SocketIO
6
- from flask_session import Session
7
- import redis
8
-
9
- from config import config
10
- from chat_agent.models.base import db
11
- from chat_agent.utils.logging_config import setup_logging
12
- from chat_agent.utils.error_handler import set_error_handler, ErrorHandler
13
- from chat_agent.utils.connection_pool import initialize_connection_pools, get_connection_pool_manager
14
- from chat_agent.services.cache_service import initialize_cache_service, get_cache_service
15
- from chat_agent.utils.response_optimization import ResponseMiddleware
16
-
17
- # Initialize extensions
18
- socketio = SocketIO()
19
- session = Session()
20
-
21
-
22
- def create_app(config_name=None):
23
- """Application factory pattern."""
24
- if config_name is None:
25
- config_name = os.getenv('FLASK_ENV', 'development')
26
-
27
- app = Flask(__name__)
28
- app.config.from_object(config[config_name])
29
-
30
- # Setup comprehensive logging
31
- loggers = setup_logging("chat_agent", app.config.get('LOG_LEVEL', 'INFO'))
32
- app.logger = loggers['main']
33
-
34
- # Setup global error handler
35
- error_handler = ErrorHandler(loggers['error'])
36
- set_error_handler(error_handler)
37
-
38
- app.logger.info("Chat agent application starting", extra={
39
- 'config': config_name,
40
- 'debug': app.config.get('DEBUG', False),
41
- 'logging_level': app.config.get('LOG_LEVEL', 'INFO')
42
- })
43
-
44
- # Initialize connection pools for performance optimization
45
- database_url = app.config.get('SQLALCHEMY_DATABASE_URI')
46
- redis_url = app.config.get('REDIS_URL')
47
-
48
- connection_pool_manager = initialize_connection_pools(database_url, redis_url)
49
-
50
- # Configure SQLAlchemy to use connection pool
51
- if connection_pool_manager:
52
- app.config['SQLALCHEMY_ENGINE_OPTIONS'] = {
53
- 'pool_size': int(os.getenv('DB_POOL_SIZE', '10')),
54
- 'max_overflow': int(os.getenv('DB_MAX_OVERFLOW', '20')),
55
- 'pool_recycle': int(os.getenv('DB_POOL_RECYCLE', '3600')),
56
- 'pool_pre_ping': True,
57
- 'pool_timeout': int(os.getenv('DB_POOL_TIMEOUT', '30'))
58
- }
59
-
60
- # Initialize extensions with app
61
- db.init_app(app)
62
- socketio.init_app(app, cors_allowed_origins="*")
63
-
64
- # Initialize response optimization middleware
65
- ResponseMiddleware(app)
66
-
67
- # Configure Redis for sessions and caching (if available)
68
- redis_client = None
69
- if redis_url and redis_url != 'None':
70
- try:
71
- # Use connection pool manager's Redis client if available
72
- if connection_pool_manager:
73
- redis_client = connection_pool_manager.get_redis_client()
74
- else:
75
- redis_client = redis.from_url(redis_url)
76
-
77
- if redis_client:
78
- redis_client.ping() # Test connection
79
- app.config['SESSION_REDIS'] = redis_client
80
- session.init_app(app)
81
- app.logger.info("Redis connection established for sessions and caching")
82
- else:
83
- raise Exception("Redis client not available")
84
-
85
- except Exception as e:
86
- app.logger.warning(f"Redis connection failed: {e}. Sessions will use filesystem.")
87
- app.config['SESSION_TYPE'] = 'filesystem'
88
- session.init_app(app)
89
- redis_client = None
90
- else:
91
- app.logger.info("Redis disabled. Using filesystem sessions.")
92
- app.config['SESSION_TYPE'] = 'filesystem'
93
- session.init_app(app)
94
-
95
- # Initialize cache service with Redis client
96
- cache_service = initialize_cache_service(redis_client)
97
- app.logger.info(f"Cache service initialized", extra={
98
- 'redis_enabled': bool(redis_client)
99
- })
100
-
101
- # Register API blueprints
102
- from chat_agent.api import chat_bp, create_limiter, setup_error_handlers, RequestLoggingMiddleware
103
- from chat_agent.api.health import health_bp
104
- from chat_agent.api.performance_routes import performance_bp
105
- app.register_blueprint(chat_bp)
106
- app.register_blueprint(health_bp)
107
- app.register_blueprint(performance_bp)
108
-
109
- # Configure rate limiting
110
- limiter = create_limiter(app)
111
- if redis_url and redis_url != 'None':
112
- limiter.storage_uri = redis_url
113
- # If no Redis, limiter will use in-memory storage (with warning)
114
-
115
- # Setup error handlers
116
- setup_error_handlers(app)
117
-
118
- # Setup request logging middleware
119
- RequestLoggingMiddleware(app)
120
-
121
- # Add chat interface route
122
- @app.route('/')
123
- @app.route('/chat')
124
- def chat_interface():
125
- """Serve the chat interface."""
126
- from flask import render_template
127
- return render_template('chat.html')
128
-
129
- # Initialize real chat agent services
130
- from chat_agent.services.groq_client import GroqClient
131
- from chat_agent.services.language_context import LanguageContextManager
132
- from chat_agent.services.session_manager import SessionManager
133
- from chat_agent.services.chat_history import ChatHistoryManager
134
- from chat_agent.services.chat_agent import ChatAgent
135
- from chat_agent.services.programming_assistance import ProgrammingAssistanceService
136
-
137
- # Initialize services
138
- try:
139
- # Initialize Redis client
140
- redis_url = app.config.get('REDIS_URL', 'redis://localhost:6379/0')
141
- redis_client = redis.from_url(redis_url)
142
-
143
- # Test Redis connection
144
- redis_client.ping()
145
- print("✅ Redis connection successful")
146
-
147
- groq_client = GroqClient()
148
- language_context_manager = LanguageContextManager()
149
- session_manager = SessionManager(redis_client)
150
- chat_history_manager = ChatHistoryManager(redis_client)
151
- programming_assistance_service = ProgrammingAssistanceService()
152
-
153
- # Initialize main chat agent
154
- chat_agent = ChatAgent(
155
- groq_client=groq_client,
156
- language_context_manager=language_context_manager,
157
- session_manager=session_manager,
158
- chat_history_manager=chat_history_manager,
159
- programming_assistance_service=programming_assistance_service
160
- )
161
-
162
- print("✅ Chat agent services initialized successfully")
163
-
164
- except Exception as e:
165
- print(f"⚠️ Error initializing chat agent services: {e}")
166
- print("🔄 Falling back to demo mode")
167
- chat_agent = None
168
-
169
- # Store session mapping for WebSocket connections
170
- websocket_sessions = {}
171
-
172
- # Initialize WebSocket handlers for chat interface
173
- @socketio.on('connect')
174
- def handle_connect(auth=None):
175
- """Handle WebSocket connection for chat interface."""
176
- from flask_socketio import emit
177
- from flask import request
178
- import uuid
179
-
180
- try:
181
- # Create a new session for this connection
182
- user_id = f"user_{request.sid}" # Use socket ID as user ID for demo
183
-
184
- if chat_agent and session_manager:
185
- session = session_manager.create_session(user_id, language='python')
186
- websocket_sessions[request.sid] = session.id
187
-
188
- emit('connection_status', {
189
- 'status': 'connected',
190
- 'session_id': session.id,
191
- 'language': session.language,
192
- 'message_count': session.message_count,
193
- 'timestamp': datetime.now().isoformat()
194
- })
195
-
196
- print(f"WebSocket connected: session={session.id}, user={user_id}")
197
- else:
198
- # Fallback to demo mode
199
- session_id = str(uuid.uuid4())
200
- websocket_sessions[request.sid] = session_id
201
-
202
- emit('connection_status', {
203
- 'status': 'connected',
204
- 'session_id': session_id,
205
- 'language': 'python',
206
- 'message_count': 0,
207
- 'timestamp': datetime.now().isoformat()
208
- })
209
-
210
- print(f"WebSocket connected (demo mode): session={session_id}, user={user_id}")
211
-
212
- except Exception as e:
213
- print(f"Error connecting WebSocket: {e}")
214
- emit('error', {'message': 'Connection failed', 'code': 'CONNECTION_ERROR'})
215
-
216
- @socketio.on('disconnect')
217
- def handle_disconnect(reason=None):
218
- """Handle WebSocket disconnection."""
219
- from flask import request
220
-
221
- # Clean up session mapping
222
- if request.sid in websocket_sessions:
223
- session_id = websocket_sessions[request.sid]
224
- del websocket_sessions[request.sid]
225
- print(f"WebSocket disconnected: session={session_id}")
226
- else:
227
- print("WebSocket disconnected")
228
-
229
- @socketio.on('message')
230
- def handle_message(data):
231
- """Handle chat messages using real chat agent."""
232
- from flask_socketio import emit
233
- from flask import request
234
-
235
- try:
236
- print(f"Received message: {data}")
237
-
238
- # Get session ID for this connection
239
- if request.sid not in websocket_sessions:
240
- emit('error', {'message': 'No active session', 'code': 'NO_SESSION'})
241
- return
242
-
243
- session_id = websocket_sessions[request.sid]
244
- content = data.get('content', '').strip()
245
- language = data.get('language', 'python')
246
-
247
- if not content:
248
- emit('error', {'message': 'Empty message received', 'code': 'EMPTY_MESSAGE'})
249
- return
250
-
251
- # Process message with real chat agent
252
- emit('response_start', {
253
- 'session_id': session_id,
254
- 'language': language,
255
- 'timestamp': datetime.now().isoformat()
256
- })
257
-
258
- try:
259
- if chat_agent:
260
- # Use the real chat agent to process the message
261
- print(f"🤖 Processing message with chat agent: '{content}' (language: {language})")
262
- result = chat_agent.process_message(session_id, content, language)
263
-
264
- # Extract response content from the result dictionary
265
- if isinstance(result, dict) and 'response' in result:
266
- response = result['response']
267
- print(f"✅ Chat agent response: {response[:100]}..." if len(response) > 100 else f"✅ Chat agent response: {response}")
268
- else:
269
- print(f"✅ Unexpected response format: {type(result)}, value: {result}")
270
- response = str(result)
271
- else:
272
- # Fallback response if chat agent is not available
273
- response = f"I understand you're asking about: '{content}'. I'm currently in demo mode, but I can help you with {language} programming concepts, debugging, and best practices. The full AI-powered assistant will provide more detailed responses."
274
-
275
- # Ensure response is a string before processing
276
- if not isinstance(response, str):
277
- response = str(response)
278
-
279
- # Send response in chunks to simulate streaming
280
- words = response.split()
281
- chunk_size = 5
282
- total_chunks = (len(words) + chunk_size - 1) // chunk_size
283
-
284
- for i in range(0, len(words), chunk_size):
285
- chunk = ' '.join(words[i:i+chunk_size]) + ' '
286
- emit('response_chunk', {
287
- 'content': chunk,
288
- 'timestamp': datetime.now().isoformat()
289
- })
290
- socketio.sleep(0.02) # Small delay for streaming effect
291
-
292
- emit('response_complete', {
293
- 'message_id': str(uuid.uuid4()),
294
- 'total_chunks': total_chunks,
295
- 'processing_time': 1.0,
296
- 'timestamp': datetime.now().isoformat()
297
- })
298
-
299
- except Exception as e:
300
- print(f"❌ Error processing message with chat agent: {e}")
301
- # Fallback to demo response if chat agent fails
302
- demo_response = f"I apologize, but I'm having trouble processing your request right now. You asked about: '{content}'. Please try again in a moment, or check that the Groq API key is properly configured."
303
-
304
- emit('response_chunk', {
305
- 'content': demo_response,
306
- 'timestamp': datetime.now().isoformat()
307
- })
308
-
309
- emit('response_complete', {
310
- 'message_id': str(uuid.uuid4()),
311
- 'total_chunks': 1,
312
- 'processing_time': 0.1,
313
- 'timestamp': datetime.now().isoformat()
314
- })
315
-
316
- except Exception as e:
317
- print(f"Error handling message: {e}")
318
- emit('error', {'message': 'Failed to process message', 'code': 'PROCESSING_ERROR'})
319
-
320
- @socketio.on('language_switch')
321
- def handle_language_switch(data):
322
- """Handle language switching using real chat agent."""
323
- from flask_socketio import emit
324
- from flask import request
325
-
326
- try:
327
- # Get session ID for this connection
328
- if request.sid not in websocket_sessions:
329
- emit('error', {'message': 'No active session', 'code': 'NO_SESSION'})
330
- return
331
-
332
- session_id = websocket_sessions[request.sid]
333
- new_language = data.get('language', 'python')
334
-
335
- language_names = {
336
- 'python': 'Python',
337
- 'javascript': 'JavaScript',
338
- 'java': 'Java',
339
- 'cpp': 'C++',
340
- 'csharp': 'C#',
341
- 'go': 'Go',
342
- 'rust': 'Rust',
343
- 'typescript': 'TypeScript'
344
- }
345
-
346
- try:
347
- if chat_agent:
348
- # Use real chat agent to switch language
349
- result = chat_agent.switch_language(session_id, new_language)
350
-
351
- emit('language_switched', {
352
- 'previous_language': result.get('previous_language', 'python'),
353
- 'new_language': result.get('new_language', new_language),
354
- 'message': result.get('message', f'Language switched to {language_names.get(new_language, new_language)}'),
355
- 'timestamp': datetime.now().isoformat()
356
- })
357
-
358
- print(f"🔄 Language switched to: {new_language} for session {session_id}")
359
- else:
360
- # Fallback for demo mode
361
- emit('language_switched', {
362
- 'previous_language': 'python',
363
- 'new_language': new_language,
364
- 'message': f"Switched to {language_names.get(new_language, new_language)}. I'm now ready to help you with {language_names.get(new_language, new_language)} programming!",
365
- 'timestamp': datetime.now().isoformat()
366
- })
367
-
368
- print(f"🔄 Language switched to: {new_language} (demo mode)")
369
-
370
- except Exception as e:
371
- print(f"❌ Error switching language: {e}")
372
- emit('error', {'message': 'Failed to switch language', 'code': 'LANGUAGE_SWITCH_ERROR'})
373
-
374
- except Exception as e:
375
- print(f"Error handling language switch: {e}")
376
- emit('error', {'message': 'Failed to switch language', 'code': 'LANGUAGE_SWITCH_ERROR'})
377
-
378
- # Add error handlers for WebSocket
379
- @socketio.on_error_default
380
- def default_error_handler(e):
381
- """Handle WebSocket errors."""
382
- print(f"WebSocket error: {e}")
383
- from flask_socketio import emit
384
- emit('error', {'message': 'Connection error occurred', 'code': 'WEBSOCKET_ERROR'})
385
-
386
- # Import datetime for timestamps
387
- from datetime import datetime
388
- import uuid
389
-
390
- return app
391
-
392
-
393
- if __name__ == '__main__':
394
- app = create_app()
395
- socketio.run(app, debug=True, host='0.0.0.0', port=5000)
 
1
+ """Main application entry point for the multi-language chat agent."""
2
+
3
+ import os
4
+ from flask import Flask
5
+ from flask_socketio import SocketIO
6
+ from flask_session import Session
7
+ import redis
8
+
9
+ from config import config
10
+ from chat_agent.models.base import db
11
+ from chat_agent.utils.logging_config import setup_logging
12
+ from chat_agent.utils.error_handler import set_error_handler, ErrorHandler
13
+ from chat_agent.utils.connection_pool import initialize_connection_pools, get_connection_pool_manager
14
+ from chat_agent.services.cache_service import initialize_cache_service, get_cache_service
15
+ from chat_agent.utils.response_optimization import ResponseMiddleware
16
+
17
+ # Initialize extensions
18
+ socketio = SocketIO()
19
+ session = Session()
20
+
21
+
22
+ def create_app(config_name=None):
23
+ """Application factory pattern."""
24
+ if config_name is None:
25
+ config_name = os.getenv('FLASK_ENV', 'development')
26
+
27
+ app = Flask(__name__)
28
+ app.config.from_object(config[config_name])
29
+
30
+ # Setup comprehensive logging
31
+ loggers = setup_logging("chat_agent", app.config.get('LOG_LEVEL', 'INFO'))
32
+ app.logger = loggers['main']
33
+
34
+ # Setup global error handler
35
+ error_handler = ErrorHandler(loggers['error'])
36
+ set_error_handler(error_handler)
37
+
38
+ app.logger.info("Chat agent application starting", extra={
39
+ 'config': config_name,
40
+ 'debug': app.config.get('DEBUG', False),
41
+ 'logging_level': app.config.get('LOG_LEVEL', 'INFO')
42
+ })
43
+
44
+ # Initialize connection pools for performance optimization
45
+ database_url = app.config.get('SQLALCHEMY_DATABASE_URI')
46
+ redis_url = app.config.get('REDIS_URL')
47
+
48
+ connection_pool_manager = initialize_connection_pools(database_url, redis_url)
49
+
50
+ # Configure SQLAlchemy to use connection pool
51
+ if connection_pool_manager:
52
+ app.config['SQLALCHEMY_ENGINE_OPTIONS'] = {
53
+ 'pool_size': int(os.getenv('DB_POOL_SIZE', '10')),
54
+ 'max_overflow': int(os.getenv('DB_MAX_OVERFLOW', '20')),
55
+ 'pool_recycle': int(os.getenv('DB_POOL_RECYCLE', '3600')),
56
+ 'pool_pre_ping': True,
57
+ 'pool_timeout': int(os.getenv('DB_POOL_TIMEOUT', '30'))
58
+ }
59
+
60
+ # Initialize extensions with app
61
+ db.init_app(app)
62
+ socketio.init_app(app, cors_allowed_origins="*")
63
+
64
+ # Initialize response optimization middleware
65
+ ResponseMiddleware(app)
66
+
67
+ # Configure Redis for sessions and caching (if available)
68
+ redis_client = None
69
+ if redis_url and redis_url != 'None':
70
+ try:
71
+ # Use connection pool manager's Redis client if available
72
+ if connection_pool_manager:
73
+ redis_client = connection_pool_manager.get_redis_client()
74
+ else:
75
+ redis_client = redis.from_url(redis_url)
76
+
77
+ if redis_client:
78
+ redis_client.ping() # Test connection
79
+ app.config['SESSION_REDIS'] = redis_client
80
+ session.init_app(app)
81
+ app.logger.info("Redis connection established for sessions and caching")
82
+ else:
83
+ raise Exception("Redis client not available")
84
+
85
+ except Exception as e:
86
+ app.logger.warning(f"Redis connection failed: {e}. Sessions will use filesystem.")
87
+ app.config['SESSION_TYPE'] = 'filesystem'
88
+ session.init_app(app)
89
+ redis_client = None
90
+ else:
91
+ app.logger.info("Redis disabled. Using filesystem sessions.")
92
+ app.config['SESSION_TYPE'] = 'filesystem'
93
+ session.init_app(app)
94
+
95
+ # Initialize cache service with Redis client
96
+ cache_service = initialize_cache_service(redis_client)
97
+ app.logger.info(f"Cache service initialized", extra={
98
+ 'redis_enabled': bool(redis_client)
99
+ })
100
+
101
+ # Register API blueprints
102
+ from chat_agent.api import chat_bp, create_limiter, setup_error_handlers, RequestLoggingMiddleware
103
+ from chat_agent.api.health import health_bp
104
+ from chat_agent.api.performance_routes import performance_bp
105
+ app.register_blueprint(chat_bp)
106
+ app.register_blueprint(health_bp)
107
+ app.register_blueprint(performance_bp)
108
+
109
+ # Configure rate limiting
110
+ limiter = create_limiter(app)
111
+ if redis_url and redis_url != 'None':
112
+ limiter.storage_uri = redis_url
113
+ # If no Redis, limiter will use in-memory storage (with warning)
114
+
115
+ # Setup error handlers
116
+ setup_error_handlers(app)
117
+
118
+ # Setup request logging middleware
119
+ RequestLoggingMiddleware(app)
120
+
121
+ # Add chat interface route
122
+ @app.route('/')
123
+ @app.route('/chat')
124
+ def chat_interface():
125
+ """Serve the chat interface."""
126
+ from flask import render_template
127
+ return render_template('chat.html')
128
+
129
+ # Initialize real chat agent services
130
+ from chat_agent.services.groq_client import GroqClient
131
+ from chat_agent.services.language_context import LanguageContextManager
132
+ from chat_agent.services.session_manager import SessionManager
133
+ from chat_agent.services.chat_history import ChatHistoryManager
134
+ from chat_agent.services.chat_agent import ChatAgent
135
+ from chat_agent.services.programming_assistance import ProgrammingAssistanceService
136
+
137
+ # Initialize services
138
+ try:
139
+ # Initialize Redis client
140
+ redis_url = app.config.get('REDIS_URL', 'redis://localhost:6379/0')
141
+ redis_client = redis.from_url(redis_url)
142
+
143
+ # Test Redis connection
144
+ redis_client.ping()
145
+ print("✅ Redis connection successful")
146
+
147
+ groq_client = GroqClient()
148
+ language_context_manager = LanguageContextManager()
149
+ session_manager = SessionManager(redis_client)
150
+ chat_history_manager = ChatHistoryManager(redis_client)
151
+ programming_assistance_service = ProgrammingAssistanceService()
152
+
153
+ # Initialize main chat agent
154
+ chat_agent = ChatAgent(
155
+ groq_client=groq_client,
156
+ language_context_manager=language_context_manager,
157
+ session_manager=session_manager,
158
+ chat_history_manager=chat_history_manager,
159
+ programming_assistance_service=programming_assistance_service
160
+ )
161
+
162
+ print("✅ Chat agent services initialized successfully")
163
+
164
+ except Exception as e:
165
+ print(f"⚠️ Error initializing chat agent services: {e}")
166
+ print("🔄 Falling back to demo mode")
167
+ chat_agent = None
168
+
169
+ # Store session mapping for WebSocket connections
170
+ websocket_sessions = {}
171
+
172
+ # Initialize WebSocket handlers for chat interface
173
+ @socketio.on('connect')
174
+ def handle_connect(auth=None):
175
+ """Handle WebSocket connection for chat interface."""
176
+ from flask_socketio import emit
177
+ from flask import request
178
+ import uuid
179
+
180
+ try:
181
+ # Create a new session for this connection
182
+ user_id = f"user_{request.sid}" # Use socket ID as user ID for demo
183
+
184
+ if chat_agent and session_manager:
185
+ session = session_manager.create_session(user_id, language='python')
186
+ websocket_sessions[request.sid] = session.id
187
+
188
+ emit('connection_status', {
189
+ 'status': 'connected',
190
+ 'session_id': session.id,
191
+ 'language': session.language,
192
+ 'message_count': session.message_count,
193
+ 'timestamp': datetime.now().isoformat()
194
+ })
195
+
196
+ print(f"WebSocket connected: session={session.id}, user={user_id}")
197
+ else:
198
+ # Fallback to demo mode
199
+ session_id = str(uuid.uuid4())
200
+ websocket_sessions[request.sid] = session_id
201
+
202
+ emit('connection_status', {
203
+ 'status': 'connected',
204
+ 'session_id': session_id,
205
+ 'language': 'python',
206
+ 'message_count': 0,
207
+ 'timestamp': datetime.now().isoformat()
208
+ })
209
+
210
+ print(f"WebSocket connected (demo mode): session={session_id}, user={user_id}")
211
+
212
+ except Exception as e:
213
+ print(f"Error connecting WebSocket: {e}")
214
+ emit('error', {'message': 'Connection failed', 'code': 'CONNECTION_ERROR'})
215
+
216
+ @socketio.on('disconnect')
217
+ def handle_disconnect(reason=None):
218
+ """Handle WebSocket disconnection."""
219
+ from flask import request
220
+
221
+ # Clean up session mapping
222
+ if request.sid in websocket_sessions:
223
+ session_id = websocket_sessions[request.sid]
224
+ del websocket_sessions[request.sid]
225
+ print(f"WebSocket disconnected: session={session_id}")
226
+ else:
227
+ print("WebSocket disconnected")
228
+
229
+ @socketio.on('message')
230
+ def handle_message(data):
231
+ """Handle chat messages using real chat agent."""
232
+ from flask_socketio import emit
233
+ from flask import request
234
+
235
+ try:
236
+ print(f"Received message: {data}")
237
+
238
+ # Get session ID for this connection
239
+ if request.sid not in websocket_sessions:
240
+ emit('error', {'message': 'No active session', 'code': 'NO_SESSION'})
241
+ return
242
+
243
+ session_id = websocket_sessions[request.sid]
244
+ content = data.get('content', '').strip()
245
+ language = data.get('language', 'python')
246
+
247
+ if not content:
248
+ emit('error', {'message': 'Empty message received', 'code': 'EMPTY_MESSAGE'})
249
+ return
250
+
251
+ # Process message with real chat agent
252
+ emit('response_start', {
253
+ 'session_id': session_id,
254
+ 'language': language,
255
+ 'timestamp': datetime.now().isoformat()
256
+ })
257
+
258
+ try:
259
+ if chat_agent:
260
+ # Use the real chat agent to process the message
261
+ print(f"🤖 Processing message with chat agent: '{content}' (language: {language})")
262
+ result = chat_agent.process_message(session_id, content, language)
263
+
264
+ # Extract response content from the result dictionary
265
+ if isinstance(result, dict) and 'response' in result:
266
+ response = result['response']
267
+ print(f"✅ Chat agent response: {response[:100]}..." if len(response) > 100 else f"✅ Chat agent response: {response}")
268
+ else:
269
+ print(f"✅ Unexpected response format: {type(result)}, value: {result}")
270
+ response = str(result)
271
+ else:
272
+ # Fallback response if chat agent is not available
273
+ response = f"I understand you're asking about: '{content}'. I'm currently in demo mode, but I can help you with {language} programming concepts, debugging, and best practices. The full AI-powered assistant will provide more detailed responses."
274
+
275
+ # Ensure response is a string before processing
276
+ if not isinstance(response, str):
277
+ response = str(response)
278
+
279
+ # Send response in chunks to simulate streaming
280
+ words = response.split()
281
+ chunk_size = 5
282
+ total_chunks = (len(words) + chunk_size - 1) // chunk_size
283
+
284
+ for i in range(0, len(words), chunk_size):
285
+ chunk = ' '.join(words[i:i+chunk_size]) + ' '
286
+ emit('response_chunk', {
287
+ 'content': chunk,
288
+ 'timestamp': datetime.now().isoformat()
289
+ })
290
+ socketio.sleep(0.02) # Small delay for streaming effect
291
+
292
+ emit('response_complete', {
293
+ 'message_id': str(uuid.uuid4()),
294
+ 'total_chunks': total_chunks,
295
+ 'processing_time': 1.0,
296
+ 'timestamp': datetime.now().isoformat()
297
+ })
298
+
299
+ except Exception as e:
300
+ print(f"❌ Error processing message with chat agent: {e}")
301
+ # Fallback to demo response if chat agent fails
302
+ demo_response = f"I apologize, but I'm having trouble processing your request right now. You asked about: '{content}'. Please try again in a moment, or check that the Groq API key is properly configured."
303
+
304
+ emit('response_chunk', {
305
+ 'content': demo_response,
306
+ 'timestamp': datetime.now().isoformat()
307
+ })
308
+
309
+ emit('response_complete', {
310
+ 'message_id': str(uuid.uuid4()),
311
+ 'total_chunks': 1,
312
+ 'processing_time': 0.1,
313
+ 'timestamp': datetime.now().isoformat()
314
+ })
315
+
316
+ except Exception as e:
317
+ print(f"Error handling message: {e}")
318
+ emit('error', {'message': 'Failed to process message', 'code': 'PROCESSING_ERROR'})
319
+
320
+ @socketio.on('language_switch')
321
+ def handle_language_switch(data):
322
+ """Handle language switching using real chat agent."""
323
+ from flask_socketio import emit
324
+ from flask import request
325
+
326
+ try:
327
+ # Get session ID for this connection
328
+ if request.sid not in websocket_sessions:
329
+ emit('error', {'message': 'No active session', 'code': 'NO_SESSION'})
330
+ return
331
+
332
+ session_id = websocket_sessions[request.sid]
333
+ new_language = data.get('language', 'python')
334
+
335
+ language_names = {
336
+ 'python': 'Python',
337
+ 'javascript': 'JavaScript',
338
+ 'java': 'Java',
339
+ 'cpp': 'C++',
340
+ 'csharp': 'C#',
341
+ 'go': 'Go',
342
+ 'rust': 'Rust',
343
+ 'typescript': 'TypeScript'
344
+ }
345
+
346
+ try:
347
+ if chat_agent:
348
+ # Use real chat agent to switch language
349
+ result = chat_agent.switch_language(session_id, new_language)
350
+
351
+ emit('language_switched', {
352
+ 'previous_language': result.get('previous_language', 'python'),
353
+ 'new_language': result.get('new_language', new_language),
354
+ 'message': result.get('message', f'Language switched to {language_names.get(new_language, new_language)}'),
355
+ 'timestamp': datetime.now().isoformat()
356
+ })
357
+
358
+ print(f"🔄 Language switched to: {new_language} for session {session_id}")
359
+ else:
360
+ # Fallback for demo mode
361
+ emit('language_switched', {
362
+ 'previous_language': 'python',
363
+ 'new_language': new_language,
364
+ 'message': f"Switched to {language_names.get(new_language, new_language)}. I'm now ready to help you with {language_names.get(new_language, new_language)} programming!",
365
+ 'timestamp': datetime.now().isoformat()
366
+ })
367
+
368
+ print(f"🔄 Language switched to: {new_language} (demo mode)")
369
+
370
+ except Exception as e:
371
+ print(f"❌ Error switching language: {e}")
372
+ emit('error', {'message': 'Failed to switch language', 'code': 'LANGUAGE_SWITCH_ERROR'})
373
+
374
+ except Exception as e:
375
+ print(f"Error handling language switch: {e}")
376
+ emit('error', {'message': 'Failed to switch language', 'code': 'LANGUAGE_SWITCH_ERROR'})
377
+
378
+ # Add error handlers for WebSocket
379
+ @socketio.on_error_default
380
+ def default_error_handler(e):
381
+ """Handle WebSocket errors."""
382
+ print(f"WebSocket error: {e}")
383
+ from flask_socketio import emit
384
+ emit('error', {'message': 'Connection error occurred', 'code': 'WEBSOCKET_ERROR'})
385
+
386
+ # Import datetime for timestamps
387
+ from datetime import datetime
388
+ import uuid
389
+
390
+ return app
391
+
392
+
393
+ if __name__ == '__main__':
394
+ app = create_app()
395
+ socketio.run(app, debug=True, host='0.0.0.0', port=7860)