webtap-tool 0.1.3__py3-none-any.whl → 0.1.4__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.

Potentially problematic release.


This version of webtap-tool might be problematic. Click here for more details.

webtap/__init__.py CHANGED
@@ -9,6 +9,7 @@ PUBLIC API:
9
9
  - main: Entry point function for CLI
10
10
  """
11
11
 
12
+ import atexit
12
13
  import sys
13
14
  import logging
14
15
 
@@ -45,12 +46,15 @@ def main():
45
46
 
46
47
 
47
48
  def _start_api_server_safely():
48
- """Start API server with error handling."""
49
+ """Start API server with error handling and cleanup registration."""
49
50
  try:
50
51
  thread = start_api_server(app.state)
51
52
  if thread and app.state:
52
53
  app.state.api_thread = thread
53
54
  logger.info("API server started on port 8765")
55
+
56
+ # Register cleanup to shut down API server on exit
57
+ atexit.register(lambda: app.state.cleanup() if app.state else None)
54
58
  else:
55
59
  logger.info("Port 8765 in use by another instance")
56
60
  except Exception as e:
webtap/api.py CHANGED
@@ -50,22 +50,54 @@ api.add_middleware(
50
50
  app_state = None
51
51
 
52
52
 
53
- @api.get("/pages")
54
- async def list_pages() -> Dict[str, Any]:
55
- """List available Chrome pages for extension selection."""
53
+ @api.get("/health")
54
+ async def health_check() -> Dict[str, Any]:
55
+ """Quick health check endpoint for extension."""
56
+ return {"status": "ok", "pid": os.getpid()}
57
+
58
+
59
+ @api.get("/info")
60
+ async def get_info() -> Dict[str, Any]:
61
+ """Combined endpoint for pages and instance info - reduces round trips."""
56
62
  if not app_state:
57
- return {"error": "WebTap not initialized", "pages": []}
63
+ return {"error": "WebTap not initialized", "pages": [], "pid": os.getpid()}
64
+
65
+ # Get pages
66
+ pages_data = app_state.service.list_pages()
67
+
68
+ # Get instance info
69
+ connected_to = None
70
+ if app_state.cdp.is_connected and app_state.cdp.page_info:
71
+ connected_to = app_state.cdp.page_info.get("title", "Untitled")
58
72
 
59
- return app_state.service.list_pages()
73
+ return {
74
+ "pid": os.getpid(),
75
+ "connected_to": connected_to,
76
+ "events": app_state.service.event_count,
77
+ "pages": pages_data.get("pages", []),
78
+ "error": pages_data.get("error"),
79
+ }
60
80
 
61
81
 
62
82
  @api.get("/status")
63
83
  async def get_status() -> Dict[str, Any]:
64
- """Get current connection status and event count."""
84
+ """Get comprehensive status including connection, events, and fetch details."""
65
85
  if not app_state:
66
86
  return {"connected": False, "error": "WebTap not initialized", "events": 0}
67
87
 
68
- return app_state.service.get_status()
88
+ status = app_state.service.get_status()
89
+
90
+ # Add fetch details if fetch is enabled
91
+ if status.get("fetch_enabled"):
92
+ fetch_service = app_state.service.fetch
93
+ paused_list = fetch_service.get_paused_list()
94
+ status["fetch_details"] = {
95
+ "paused_requests": paused_list,
96
+ "paused_count": len(paused_list),
97
+ "response_stage": fetch_service.enable_response_stage,
98
+ }
99
+
100
+ return status
69
101
 
70
102
 
71
103
  @api.post("/connect")
@@ -108,25 +140,6 @@ async def set_fetch_interception(request: FetchRequest) -> Dict[str, Any]:
108
140
  return result
109
141
 
110
142
 
111
- @api.get("/fetch/paused")
112
- async def get_paused_requests() -> Dict[str, Any]:
113
- """Get list of currently paused fetch requests."""
114
- if not app_state:
115
- return {"error": "WebTap not initialized", "requests": []}
116
-
117
- fetch_service = app_state.service.fetch
118
- if not fetch_service.enabled:
119
- return {"enabled": False, "requests": []}
120
-
121
- paused_list = fetch_service.get_paused_list()
122
- return {
123
- "enabled": True,
124
- "requests": paused_list,
125
- "count": len(paused_list),
126
- "response_stage": fetch_service.enable_response_stage,
127
- }
128
-
129
-
130
143
  @api.get("/filters/status")
131
144
  async def get_filter_status() -> Dict[str, Any]:
132
145
  """Get current filter configuration and enabled categories."""
@@ -186,19 +199,6 @@ async def disable_all_filters() -> Dict[str, Any]:
186
199
  return {"enabled": [], "total": 0}
187
200
 
188
201
 
189
- @api.get("/instance")
190
- async def get_instance_info() -> Dict[str, Any]:
191
- """Get info about this WebTap instance."""
192
- if not app_state:
193
- return {"error": "WebTap not initialized"}
194
-
195
- return {
196
- "pid": os.getpid(),
197
- "connected_to": app_state.cdp.current_page_title if app_state.cdp.is_connected else None,
198
- "events": app_state.cdp.event_count,
199
- }
200
-
201
-
202
202
  @api.post("/release")
203
203
  async def release_port() -> Dict[str, Any]:
204
204
  """Release API port for another WebTap instance."""
@@ -237,8 +237,9 @@ def start_api_server(state, host: str = "127.0.0.1", port: int = 8765) -> thread
237
237
  logger.info(f"Port {port} already in use")
238
238
  return None
239
239
 
240
- global app_state
240
+ global app_state, _shutdown_requested
241
241
  app_state = state
242
+ _shutdown_requested = False # Reset flag for new instance
242
243
 
243
244
  thread = threading.Thread(target=run_server, args=(host, port), daemon=True)
244
245
  thread.start()
@@ -249,7 +250,10 @@ def start_api_server(state, host: str = "127.0.0.1", port: int = 8765) -> thread
249
250
 
250
251
  def run_server(host: str, port: int):
251
252
  """Run the FastAPI server in a thread."""
252
- try:
253
+ import asyncio
254
+
255
+ async def run():
256
+ """Run server with proper shutdown handling."""
253
257
  config = uvicorn.Config(
254
258
  api,
255
259
  host=host,
@@ -259,30 +263,33 @@ def run_server(host: str, port: int):
259
263
  )
260
264
  server = uvicorn.Server(config)
261
265
 
262
- # Run with checking for shutdown flag
263
- import asyncio
264
-
265
- loop = asyncio.new_event_loop()
266
- asyncio.set_event_loop(loop)
266
+ # Start server in background task
267
+ serve_task = asyncio.create_task(server.serve())
267
268
 
268
- async def serve():
269
- await server.serve()
270
-
271
- # Start serving
272
- task = loop.create_task(serve())
273
-
274
- # Check for shutdown flag
269
+ # Wait for shutdown signal
275
270
  while not _shutdown_requested:
276
- loop.run_until_complete(asyncio.sleep(0.1))
277
- if task.done():
271
+ await asyncio.sleep(0.1)
272
+ if serve_task.done():
278
273
  break
279
274
 
280
- # Shutdown if requested
281
- if _shutdown_requested:
275
+ # Trigger shutdown
276
+ if not serve_task.done():
282
277
  logger.info("API server shutting down")
283
278
  server.should_exit = True
284
- loop.run_until_complete(server.shutdown())
279
+ # Wait a bit for graceful shutdown
280
+ try:
281
+ await asyncio.wait_for(serve_task, timeout=1.0)
282
+ except asyncio.TimeoutError:
283
+ logger.debug("Server task timeout - cancelling")
284
+ serve_task.cancel()
285
+ try:
286
+ await serve_task
287
+ except asyncio.CancelledError:
288
+ pass
285
289
 
290
+ try:
291
+ # Use asyncio.run() which properly cleans up
292
+ asyncio.run(run())
286
293
  except Exception as e:
287
294
  logger.error(f"API server failed: {e}")
288
295
 
webtap/app.py CHANGED
@@ -36,6 +36,21 @@ class WebTapState:
36
36
  """Initialize service with self reference after dataclass init."""
37
37
  self.service = WebTapService(self)
38
38
 
39
+ def cleanup(self):
40
+ """Cleanup resources on exit."""
41
+ # Disconnect CDP if connected
42
+ if self.cdp.is_connected:
43
+ self.cdp.disconnect()
44
+
45
+ # Stop API server if we own it
46
+ if self.api_thread and self.api_thread.is_alive():
47
+ # Import here to avoid circular dependency
48
+ import webtap.api
49
+
50
+ webtap.api._shutdown_requested = True
51
+ # Wait up to 1 second for graceful shutdown
52
+ self.api_thread.join(timeout=1.0)
53
+
39
54
 
40
55
  # Must be created before command imports for decorator registration
41
56
  app = App(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: webtap-tool
3
- Version: 0.1.3
3
+ Version: 0.1.4
4
4
  Summary: Terminal-based web page inspector for AI debugging sessions
5
5
  Author-email: Fredrik Angelsen <fredrikangelsen@gmail.com>
6
6
  Classifier: Development Status :: 3 - Alpha
@@ -1,7 +1,7 @@
1
1
  webtap/VISION.md,sha256=kfoJfEPVc4chOrD9tNMDmYBY9rX9KB-286oZj70ALCE,7681
2
- webtap/__init__.py,sha256=4MD5ir_kyfHcI3kND_As9jF-UUqGEzWKV5Cg6PKzef4,1787
3
- webtap/api.py,sha256=1VV_YPwvGuYanDm5M_NuWUYiGIQbPd3IKicK5Jplq44,7987
4
- webtap/app.py,sha256=ISPSmwqCZ2R_kVDmFEsBLltzfbHGUkzcczTGCs2KcDI,2738
2
+ webtap/__init__.py,sha256=6sTctXhLKByd8TnKJ99Y4o6xv7AbbPJ37S6YMNsQGBM,1970
3
+ webtap/api.py,sha256=mfAqxQfu2lF91jiI6kHQnpmwtwq0Hh9UtuV8ApENXe0,8504
4
+ webtap/app.py,sha256=M6-tCT6uvR5aMMYYUymYrXhq4PaUlHVYTv7MDN_svdQ,3246
5
5
  webtap/filters.py,sha256=nphF2bFRbFtS2ue-CbV1uzKpuK3IYBbwjLeLhMDdLEk,11034
6
6
  webtap/cdp/README.md,sha256=0TS0V_dRgRAzBqhddpXWD4S0YVi5wI4JgFJSll_KUBE,5660
7
7
  webtap/cdp/__init__.py,sha256=c6NFG0XJnAa5GTe9MLr9mDZcLZqoTQN7A1cvvOfLcgY,453
@@ -37,7 +37,7 @@ webtap/services/fetch.py,sha256=nl6bpU2Vnf40kau4-mqAnIkhC-7Lx2vbTJKUglz9KnE,1360
37
37
  webtap/services/main.py,sha256=HcXdPuI7hzsxsNvfN0npGhj_M7HObc83Lr3fuy7BMeE,5673
38
38
  webtap/services/network.py,sha256=0o_--F6YvmXqqFqrcjL1gc6Vr9V1Ytb_U7r_DSUWupA,3444
39
39
  webtap/services/setup.py,sha256=dXzqlXR37-chZO2qCsuiVq9N7fELXtND5jH_9QQwsws,7932
40
- webtap_tool-0.1.3.dist-info/METADATA,sha256=8fezx8WvoSf5sTT5-2ibcGwLDvVldjPLpGndETihBIw,17457
41
- webtap_tool-0.1.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
42
- webtap_tool-0.1.3.dist-info/entry_points.txt,sha256=iFe575I0CIb1MbfPt0oX2VYyY5gSU_dA551PKVR83TU,39
43
- webtap_tool-0.1.3.dist-info/RECORD,,
40
+ webtap_tool-0.1.4.dist-info/METADATA,sha256=xX7oPMbWWVeiFFRYbCB7V87iEMDoqh9JXfog5AY0gXM,17457
41
+ webtap_tool-0.1.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
42
+ webtap_tool-0.1.4.dist-info/entry_points.txt,sha256=iFe575I0CIb1MbfPt0oX2VYyY5gSU_dA551PKVR83TU,39
43
+ webtap_tool-0.1.4.dist-info/RECORD,,