escobar 0.1.89__py3-none-any.whl → 0.1.90__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. escobar/_version.py +1 -1
  2. escobar/handlers.py +107 -0
  3. escobar/labextension/package.json +2 -2
  4. escobar/labextension/schemas/escobar/package.json.orig +1 -1
  5. escobar/labextension/static/{237.23439249688997c395a8.js → 237.d012347a7c8fb32c64ae.js} +1 -1
  6. escobar/labextension/static/{remoteEntry.a8ae0b901c4a30b269e4.js → remoteEntry.c9a1accf3c70050fa880.js} +1 -1
  7. {escobar-0.1.89.data → escobar-0.1.90.data}/data/share/jupyter/labextensions/escobar/package.json +2 -2
  8. {escobar-0.1.89.data → escobar-0.1.90.data}/data/share/jupyter/labextensions/escobar/schemas/escobar/package.json.orig +1 -1
  9. escobar-0.1.89.data/data/share/jupyter/labextensions/escobar/static/237.23439249688997c395a8.js → escobar-0.1.90.data/data/share/jupyter/labextensions/escobar/static/237.d012347a7c8fb32c64ae.js +1 -1
  10. escobar-0.1.89.data/data/share/jupyter/labextensions/escobar/static/remoteEntry.a8ae0b901c4a30b269e4.js → escobar-0.1.90.data/data/share/jupyter/labextensions/escobar/static/remoteEntry.c9a1accf3c70050fa880.js +1 -1
  11. {escobar-0.1.89.dist-info → escobar-0.1.90.dist-info}/METADATA +1 -1
  12. {escobar-0.1.89.dist-info → escobar-0.1.90.dist-info}/RECORD +27 -27
  13. {escobar-0.1.89.data → escobar-0.1.90.data}/data/share/jupyter/labextensions/escobar/install.json +0 -0
  14. {escobar-0.1.89.data → escobar-0.1.90.data}/data/share/jupyter/labextensions/escobar/schemas/escobar/plugin.json +0 -0
  15. {escobar-0.1.89.data → escobar-0.1.90.data}/data/share/jupyter/labextensions/escobar/static/304.bf7e91be734e5b36cdc9.js +0 -0
  16. {escobar-0.1.89.data → escobar-0.1.90.data}/data/share/jupyter/labextensions/escobar/static/346.8a1e61ca6789b6fddfa7.js +0 -0
  17. {escobar-0.1.89.data → escobar-0.1.90.data}/data/share/jupyter/labextensions/escobar/static/379.40dd59dc19d4a6b42d25.js +0 -0
  18. {escobar-0.1.89.data → escobar-0.1.90.data}/data/share/jupyter/labextensions/escobar/static/57.17e53b4b9a954f39c4d8.js +0 -0
  19. {escobar-0.1.89.data → escobar-0.1.90.data}/data/share/jupyter/labextensions/escobar/static/648.a7d314faeacc762d891d.js +0 -0
  20. {escobar-0.1.89.data → escobar-0.1.90.data}/data/share/jupyter/labextensions/escobar/static/666.3bc65aac3a3be183ee19.js +0 -0
  21. {escobar-0.1.89.data → escobar-0.1.90.data}/data/share/jupyter/labextensions/escobar/static/874.c539726f31a1baa0267e.js +0 -0
  22. {escobar-0.1.89.data → escobar-0.1.90.data}/data/share/jupyter/labextensions/escobar/static/986.cbcf9d7c1cd8d06be435.js +0 -0
  23. {escobar-0.1.89.data → escobar-0.1.90.data}/data/share/jupyter/labextensions/escobar/static/style.js +0 -0
  24. {escobar-0.1.89.data → escobar-0.1.90.data}/data/share/jupyter/labextensions/escobar/static/third-party-licenses.json +0 -0
  25. {escobar-0.1.89.dist-info → escobar-0.1.90.dist-info}/WHEEL +0 -0
  26. {escobar-0.1.89.dist-info → escobar-0.1.90.dist-info}/entry_points.txt +0 -0
  27. {escobar-0.1.89.dist-info → escobar-0.1.90.dist-info}/licenses/LICENSE +0 -0
escobar/_version.py CHANGED
@@ -1,4 +1,4 @@
1
1
  # This file is auto-generated by Hatchling. As such, do not:
2
2
  # - modify
3
3
  # - track in version control e.g. be sure to add to .gitignore
4
- __version__ = VERSION = '0.1.89'
4
+ __version__ = VERSION = '0.1.90'
escobar/handlers.py CHANGED
@@ -6,6 +6,8 @@ import websockets
6
6
  import ssl
7
7
  import logging
8
8
  import time
9
+ import threading
10
+ import psutil
9
11
  from urllib.parse import urlparse, urlunparse
10
12
  from jupyter_server.base.handlers import JupyterHandler
11
13
  from jupyter_server.utils import url_path_join
@@ -152,8 +154,91 @@ class ProxyHandler(JupyterHandler):
152
154
  class WebSocketProxyHandler(tornado.websocket.WebSocketHandler):
153
155
  """
154
156
  WebSocket proxy handler that forwards connections from /ws to target server
157
+ Enhanced with comprehensive logging for debugging intermittent connection issues
155
158
  """
156
159
 
160
+ # Class-level connection tracking
161
+ _connection_count = 0
162
+ _active_connections = {}
163
+
164
+ def _log_system_state(self, context=""):
165
+ """Log current system state for debugging"""
166
+ try:
167
+ # System resource information
168
+ cpu_percent = psutil.cpu_percent(interval=0.1)
169
+ memory = psutil.virtual_memory()
170
+
171
+ print(f"[ESCOBAR-WS] === SYSTEM STATE {context} ===")
172
+ print(f"[ESCOBAR-WS] CPU Usage: {cpu_percent}%")
173
+ print(f"[ESCOBAR-WS] Memory Usage: {memory.percent}% ({memory.used / 1024 / 1024:.1f}MB used)")
174
+ print(f"[ESCOBAR-WS] Active Connections: {len(self._active_connections)}")
175
+ print(f"[ESCOBAR-WS] Total Connections Created: {self._connection_count}")
176
+ print(f"[ESCOBAR-WS] Current Thread: {threading.current_thread().name}")
177
+ print(f"[ESCOBAR-WS] === END SYSTEM STATE ===")
178
+ except Exception as e:
179
+ print(f"[ESCOBAR-WS] Error logging system state: {e}")
180
+
181
+ def _log_connection_lifecycle(self, event, details=None):
182
+ """Log connection lifecycle events with timing"""
183
+ timestamp = time.time()
184
+ connection_id = getattr(self, 'connection_id', 'UNKNOWN')
185
+
186
+ print(f"[ESCOBAR-WS] === CONNECTION LIFECYCLE EVENT ===")
187
+ print(f"[ESCOBAR-WS] Event: {event}")
188
+ print(f"[ESCOBAR-WS] Connection ID: {connection_id}")
189
+ print(f"[ESCOBAR-WS] Timestamp: {timestamp}")
190
+ print(f"[ESCOBAR-WS] Human Time: {time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(timestamp))}")
191
+ if details:
192
+ print(f"[ESCOBAR-WS] Details: {details}")
193
+ print(f"[ESCOBAR-WS] === END LIFECYCLE EVENT ===")
194
+
195
+ def _log_message_timing(self, direction, message_size, start_time=None):
196
+ """Log message timing and throughput"""
197
+ current_time = time.time()
198
+
199
+ print(f"[ESCOBAR-WS] === MESSAGE TIMING ===")
200
+ print(f"[ESCOBAR-WS] Direction: {direction}")
201
+ print(f"[ESCOBAR-WS] Message Size: {message_size} bytes")
202
+ print(f"[ESCOBAR-WS] Timestamp: {current_time}")
203
+
204
+ if start_time:
205
+ duration = current_time - start_time
206
+ throughput = message_size / duration if duration > 0 else 0
207
+ print(f"[ESCOBAR-WS] Processing Duration: {duration:.4f}s")
208
+ print(f"[ESCOBAR-WS] Throughput: {throughput:.2f} bytes/sec")
209
+
210
+ print(f"[ESCOBAR-WS] === END MESSAGE TIMING ===")
211
+
212
+ def _log_target_connection_health(self):
213
+ """Log target connection health metrics"""
214
+ if not self.target_ws:
215
+ print(f"[ESCOBAR-WS] === TARGET HEALTH: NO CONNECTION ===")
216
+ return
217
+
218
+ print(f"[ESCOBAR-WS] === TARGET CONNECTION HEALTH ===")
219
+ try:
220
+ print(f"[ESCOBAR-WS] Target State: {self.target_ws.state}")
221
+ print(f"[ESCOBAR-WS] Target State Name: {self.target_ws.state.name}")
222
+ print(f"[ESCOBAR-WS] Target State Value: {self.target_ws.state.value}")
223
+
224
+ # Check if we can access additional properties
225
+ if hasattr(self.target_ws, 'ping_interval'):
226
+ print(f"[ESCOBAR-WS] Ping Interval: {self.target_ws.ping_interval}")
227
+ if hasattr(self.target_ws, 'ping_timeout'):
228
+ print(f"[ESCOBAR-WS] Ping Timeout: {self.target_ws.ping_timeout}")
229
+ if hasattr(self.target_ws, 'close_timeout'):
230
+ print(f"[ESCOBAR-WS] Close Timeout: {self.target_ws.close_timeout}")
231
+
232
+ except Exception as e:
233
+ print(f"[ESCOBAR-WS] Error checking target health: {e}")
234
+
235
+ print(f"[ESCOBAR-WS] === END TARGET HEALTH ===")
236
+
237
+ def _generate_connection_id(self):
238
+ """Generate unique connection ID for tracking"""
239
+ WebSocketProxyHandler._connection_count += 1
240
+ return f"CONN-{WebSocketProxyHandler._connection_count}-{int(time.time())}"
241
+
157
242
  def _resolve_target_url_for_docker(self, url):
158
243
  """
159
244
  Resolve target URL for Docker environment.
@@ -214,6 +299,25 @@ class WebSocketProxyHandler(tornado.websocket.WebSocketHandler):
214
299
  super().__init__(*args, **kwargs)
215
300
  self.target_ws = None
216
301
 
302
+ # Generate unique connection ID for tracking
303
+ self.connection_id = self._generate_connection_id()
304
+ self.connection_start_time = time.time()
305
+
306
+ # Add to active connections tracking
307
+ WebSocketProxyHandler._active_connections[self.connection_id] = {
308
+ 'start_time': self.connection_start_time,
309
+ 'handler': self
310
+ }
311
+
312
+ # Log connection creation
313
+ self._log_connection_lifecycle("HANDLER_CREATED", {
314
+ 'connection_id': self.connection_id,
315
+ 'total_connections': len(WebSocketProxyHandler._active_connections)
316
+ })
317
+
318
+ # Log system state at connection creation
319
+ self._log_system_state("CONNECTION_INIT")
320
+
217
321
  # Debug environment information
218
322
  print(f"[ESCOBAR-WS] Environment WEBSOCKET_PROXY_TARGET: {os.getenv('WEBSOCKET_PROXY_TARGET', 'NOT_SET')}")
219
323
  print(f"[ESCOBAR-WS] Running in container: {os.path.exists('/.dockerenv')}")
@@ -232,6 +336,9 @@ class WebSocketProxyHandler(tornado.websocket.WebSocketHandler):
232
336
  print(f"[ESCOBAR-WS] All WEBSOCKET environment vars: {websocket_env_vars}")
233
337
 
234
338
  self.is_closing = False
339
+ self.message_count_sent = 0
340
+ self.message_count_received = 0
341
+ self.last_activity_time = time.time()
235
342
 
236
343
  def _get_user_bonnie_url(self):
237
344
  """
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "escobar",
3
- "version": "0.1.89",
3
+ "version": "0.1.90",
4
4
  "description": "AI CHAT EXTENSION",
5
5
  "keywords": [
6
6
  "jupyter",
@@ -123,7 +123,7 @@
123
123
  "outputDir": "escobar/labextension",
124
124
  "schemaDir": "schema",
125
125
  "_build": {
126
- "load": "static/remoteEntry.a8ae0b901c4a30b269e4.js",
126
+ "load": "static/remoteEntry.c9a1accf3c70050fa880.js",
127
127
  "extension": "./extension",
128
128
  "style": "./style"
129
129
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "escobar",
3
- "version": "0.1.89",
3
+ "version": "0.1.90",
4
4
  "description": "AI CHAT EXTENSION",
5
5
  "keywords": [
6
6
  "jupyter",