webtap-tool 0.2.2__py3-none-any.whl → 0.3.0__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,14 +9,9 @@ PUBLIC API:
9
9
  - main: Entry point function for CLI
10
10
  """
11
11
 
12
- import atexit
13
12
  import sys
14
- import logging
15
13
 
16
14
  from webtap.app import app
17
- from webtap.api import start_api_server
18
-
19
- logger = logging.getLogger(__name__)
20
15
 
21
16
 
22
17
  def main():
@@ -27,13 +22,9 @@ def main():
27
22
  - MCP mode (with --mcp flag) for Model Context Protocol server
28
23
  - REPL mode (default) for interactive shell
29
24
 
30
- In REPL and MCP modes, the API server is started for Chrome extension
31
- integration. The API server runs in background to handle extension requests.
25
+ The API server for Chrome extension communication must be started
26
+ explicitly using the server('start') command.
32
27
  """
33
- # Start API server for Chrome extension (except in CLI mode)
34
- if "--cli" not in sys.argv:
35
- _start_api_server_safely()
36
-
37
28
  if "--mcp" in sys.argv:
38
29
  app.mcp.run()
39
30
  elif "--cli" in sys.argv:
@@ -45,20 +36,4 @@ def main():
45
36
  app.run(title="WebTap - Chrome DevTools Protocol REPL")
46
37
 
47
38
 
48
- def _start_api_server_safely():
49
- """Start API server with error handling and cleanup registration."""
50
- try:
51
- thread = start_api_server(app.state)
52
- if thread and app.state:
53
- app.state.api_thread = thread
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)
58
- else:
59
- logger.info("Port 8765 in use by another instance")
60
- except Exception as e:
61
- logger.warning(f"Failed to start API server: {e}")
62
-
63
-
64
39
  __all__ = ["app", "main"]
webtap/api.py CHANGED
@@ -199,21 +199,6 @@ async def disable_all_filters() -> Dict[str, Any]:
199
199
  return {"enabled": [], "total": 0}
200
200
 
201
201
 
202
- @api.post("/release")
203
- async def release_port() -> Dict[str, Any]:
204
- """Release API port for another WebTap instance."""
205
- logger.info("Releasing API port for another instance")
206
-
207
- # Schedule graceful shutdown after response
208
- def shutdown():
209
- # Just set the flag to stop uvicorn, don't kill the whole process
210
- global _shutdown_requested
211
- _shutdown_requested = True
212
-
213
- threading.Timer(0.5, shutdown).start()
214
- return {"message": "Releasing port 8765"}
215
-
216
-
217
202
  # Flag to signal shutdown
218
203
  _shutdown_requested = False
219
204
 
webtap/app.py CHANGED
@@ -84,6 +84,7 @@ else:
84
84
  from webtap.commands import inspect # noqa: E402, F401
85
85
  from webtap.commands import fetch # noqa: E402, F401
86
86
  from webtap.commands import body # noqa: E402, F401
87
+ from webtap.commands import server # noqa: E402, F401
87
88
  from webtap.commands import setup # noqa: E402, F401
88
89
  from webtap.commands import launch # noqa: E402, F401
89
90
 
@@ -0,0 +1,162 @@
1
+ """API server management command.
2
+
3
+ PUBLIC API:
4
+ - server: Manage API server (status/start/stop/restart)
5
+ """
6
+
7
+ import socket
8
+ import time
9
+ import logging
10
+
11
+ from webtap.app import app
12
+ from webtap.api import start_api_server
13
+
14
+ logger = logging.getLogger(__name__)
15
+
16
+ # Fixed port for API server
17
+ API_PORT = 8765
18
+
19
+
20
+ def _check_port() -> bool:
21
+ """Check if API port is in use."""
22
+ with socket.socket() as s:
23
+ try:
24
+ s.bind(("127.0.0.1", API_PORT))
25
+ return False # Port is free
26
+ except OSError:
27
+ return True # Port is in use
28
+
29
+
30
+ def _stop_server(state) -> tuple[bool, str]:
31
+ """Stop the server if this instance owns it."""
32
+ if not state.api_thread or not state.api_thread.is_alive():
33
+ return False, "Not running"
34
+
35
+ import webtap.api
36
+
37
+ webtap.api._shutdown_requested = True
38
+ state.api_thread.join(timeout=2.0)
39
+ state.api_thread = None
40
+
41
+ return True, "Server stopped"
42
+
43
+
44
+ def _start_server(state) -> tuple[bool, str]:
45
+ """Start the server on port 8765."""
46
+ # Check if already running
47
+ if state.api_thread and state.api_thread.is_alive():
48
+ return True, f"Already running on port {API_PORT}"
49
+
50
+ # Check if port is in use
51
+ if _check_port():
52
+ return False, f"Port {API_PORT} already in use by another process"
53
+
54
+ # Start the server
55
+ thread = start_api_server(state, port=API_PORT)
56
+ if thread:
57
+ state.api_thread = thread
58
+
59
+ # Register cleanup
60
+ import atexit
61
+
62
+ atexit.register(lambda: state.cleanup() if state else None)
63
+
64
+ return True, f"Server started on port {API_PORT}"
65
+ else:
66
+ return False, "Failed to start server"
67
+
68
+
69
+ @app.command(
70
+ display="markdown",
71
+ fastmcp={
72
+ "type": "prompt",
73
+ "arg_descriptions": {"action": "Server action: status (default), start, stop, or restart"},
74
+ },
75
+ )
76
+ def server(state, action: str = None) -> dict: # pyright: ignore[reportArgumentType]
77
+ """API server status and management information.
78
+
79
+ Returns current server state and available actions.
80
+ """
81
+ if action is None:
82
+ action = "status"
83
+
84
+ action = action.lower()
85
+ owns_server = bool(state.api_thread and state.api_thread.is_alive())
86
+
87
+ # Build markdown elements based on action
88
+ elements = []
89
+
90
+ if action == "status" or action not in ["start", "stop", "restart"]:
91
+ # Status information
92
+ elements.append({"type": "heading", "content": "API Server Status", "level": 2})
93
+
94
+ if owns_server:
95
+ elements.append({"type": "text", "content": "**Status:** Running"})
96
+ elements.append({"type": "text", "content": f"**Port:** {API_PORT}"})
97
+ elements.append({"type": "text", "content": f"**URL:** http://127.0.0.1:{API_PORT}"})
98
+ elements.append({"type": "text", "content": f"**Health:** http://127.0.0.1:{API_PORT}/health"})
99
+ elements.append({"type": "text", "content": "**Extension:** Ready to connect"})
100
+ else:
101
+ port_in_use = _check_port()
102
+ if port_in_use:
103
+ elements.append({"type": "alert", "message": "Port 8765 in use by another process", "level": "warning"})
104
+ elements.append({"type": "text", "content": "Cannot start server until port is free"})
105
+ else:
106
+ elements.append({"type": "text", "content": "**Status:** Not running"})
107
+ elements.append({"type": "text", "content": f"**Port:** {API_PORT} (available)"})
108
+ elements.append({"type": "text", "content": "Use `server('start')` to start the API server"})
109
+
110
+ # Available actions
111
+ elements.append({"type": "heading", "content": "Available Actions", "level": 3})
112
+ actions = [
113
+ "`server('start')` - Start the API server",
114
+ "`server('stop')` - Stop the API server",
115
+ "`server('restart')` - Restart the API server",
116
+ "`server('status')` or `server()` - Show this status",
117
+ ]
118
+ elements.append({"type": "list", "items": actions})
119
+
120
+ elif action == "start":
121
+ if owns_server:
122
+ elements.append({"type": "alert", "message": f"Server already running on port {API_PORT}", "level": "info"})
123
+ else:
124
+ success, message = _start_server(state)
125
+ if success:
126
+ elements.append({"type": "alert", "message": message, "level": "success"})
127
+ elements.append({"type": "text", "content": f"**URL:** http://127.0.0.1:{API_PORT}"})
128
+ elements.append({"type": "text", "content": f"**Health:** http://127.0.0.1:{API_PORT}/health"})
129
+ elements.append({"type": "text", "content": "Chrome extension can now connect"})
130
+ else:
131
+ elements.append({"type": "alert", "message": message, "level": "error"})
132
+
133
+ elif action == "stop":
134
+ if not owns_server:
135
+ elements.append({"type": "text", "content": "Server not running"})
136
+ else:
137
+ success, message = _stop_server(state)
138
+ if success:
139
+ elements.append({"type": "alert", "message": message, "level": "success"})
140
+ else:
141
+ elements.append({"type": "alert", "message": message, "level": "error"})
142
+
143
+ elif action == "restart":
144
+ if owns_server:
145
+ success, msg = _stop_server(state)
146
+ if not success:
147
+ elements.append({"type": "alert", "message": f"Failed to stop: {msg}", "level": "error"})
148
+ return {"elements": elements}
149
+ time.sleep(0.5)
150
+
151
+ success, msg = _start_server(state)
152
+ if success:
153
+ elements.append({"type": "alert", "message": "Server restarted", "level": "success"})
154
+ elements.append({"type": "text", "content": f"**Port:** {API_PORT}"})
155
+ elements.append({"type": "text", "content": f"**URL:** http://127.0.0.1:{API_PORT}"})
156
+ else:
157
+ elements.append({"type": "alert", "message": f"Failed to restart: {msg}", "level": "error"})
158
+
159
+ return {"elements": elements}
160
+
161
+
162
+ __all__ = ["server"]
@@ -10,7 +10,26 @@ from .filters import FilterSetupService
10
10
  from .extension import ExtensionSetupService
11
11
  from .chrome import ChromeSetupService
12
12
  from .desktop import DesktopSetupService
13
- from .platform import get_platform_info, ensure_directories
13
+ from .platform import get_platform_info, ensure_directories, APP_NAME
14
+
15
+ # Old installation paths to clean up
16
+ OLD_EXTENSION_PATH = ".config/webtap/extension"
17
+ OLD_WRAPPER_PATH = ".local/bin/wrappers/google-chrome-stable"
18
+ OLD_DESKTOP_PATH = ".local/share/applications/google-chrome.desktop"
19
+ OLD_DEBUG_DIR = ".config/google-chrome-debug"
20
+
21
+ # Path components
22
+ WRAPPERS_DIR = "wrappers"
23
+ GOOGLE_CHROME_STABLE = "google-chrome-stable"
24
+
25
+ # Size formatting constants
26
+ KB_SIZE = 1024
27
+ SIZE_FORMAT_KB = "{:.1f} KB"
28
+ SIZE_FORMAT_EMPTY = "empty"
29
+
30
+ # Mount point command
31
+ MOUNTPOINT_CMD = "mountpoint"
32
+ MOUNTPOINT_CHECK_FLAG = "-q"
14
33
 
15
34
 
16
35
  class SetupService:
@@ -108,11 +127,11 @@ class SetupService:
108
127
  result = {}
109
128
 
110
129
  # Check old extension location
111
- old_extension_path = Path.home() / ".config" / "webtap" / "extension"
130
+ old_extension_path = Path.home() / OLD_EXTENSION_PATH
112
131
  if old_extension_path.exists():
113
132
  # Calculate size
114
133
  size = sum(f.stat().st_size for f in old_extension_path.rglob("*") if f.is_file())
115
- size_str = f"{size / 1024:.1f} KB" if size > 0 else "empty"
134
+ size_str = SIZE_FORMAT_KB.format(size / KB_SIZE) if size > 0 else SIZE_FORMAT_EMPTY
116
135
 
117
136
  result["old_extension"] = {"path": str(old_extension_path), "size": size_str, "removed": False}
118
137
 
@@ -128,7 +147,7 @@ class SetupService:
128
147
  result["old_extension"]["error"] = str(e)
129
148
 
130
149
  # Check old Chrome wrapper location
131
- old_wrapper_path = Path.home() / ".local" / "bin" / "wrappers" / "google-chrome-stable"
150
+ old_wrapper_path = Path.home() / OLD_WRAPPER_PATH
132
151
  if old_wrapper_path.exists():
133
152
  result["old_wrapper"] = {"path": str(old_wrapper_path), "removed": False}
134
153
 
@@ -144,12 +163,13 @@ class SetupService:
144
163
  result["old_wrapper"]["error"] = str(e)
145
164
 
146
165
  # Check old desktop entry
147
- old_desktop_path = Path.home() / ".local" / "share" / "applications" / "google-chrome.desktop"
166
+ old_desktop_path = Path.home() / OLD_DESKTOP_PATH
148
167
  if old_desktop_path.exists():
149
168
  # Check if it's our override (contains reference to wrapper)
150
169
  try:
151
170
  content = old_desktop_path.read_text()
152
- if "wrappers/google-chrome-stable" in content or "webtap" in content.lower():
171
+ wrapper_ref = f"{WRAPPERS_DIR}/{GOOGLE_CHROME_STABLE}"
172
+ if wrapper_ref in content or APP_NAME in content.lower():
153
173
  result["old_desktop"] = {"path": str(old_desktop_path), "removed": False}
154
174
 
155
175
  if not dry_run:
@@ -162,11 +182,11 @@ class SetupService:
162
182
  pass # If we can't read it, skip it
163
183
 
164
184
  # Check for bindfs mount
165
- debug_dir = Path.home() / ".config" / "google-chrome-debug"
185
+ debug_dir = Path.home() / OLD_DEBUG_DIR
166
186
  if debug_dir.exists():
167
187
  try:
168
188
  # Check if it's a mount point
169
- output = subprocess.run(["mountpoint", "-q", str(debug_dir)], capture_output=True)
189
+ output = subprocess.run([MOUNTPOINT_CMD, MOUNTPOINT_CHECK_FLAG, str(debug_dir)], capture_output=True)
170
190
  if output.returncode == 0:
171
191
  result["bindfs_mount"] = str(debug_dir)
172
192
  except (FileNotFoundError, OSError):
@@ -168,11 +168,11 @@ class DesktopSetupService:
168
168
  # Create launcher script that directly launches Chrome
169
169
  # This avoids Rosetta warnings from nested bash scripts
170
170
  launcher_path = macos_dir / "Chrome Debug"
171
-
171
+
172
172
  # Get Chrome path from platform info
173
173
  chrome_path = self.chrome["path"]
174
174
  profile_dir = self.paths["data_dir"] / "profiles" / "default"
175
-
175
+
176
176
  launcher_content = f"""#!/bin/bash
177
177
  # Chrome Debug app launcher - direct Chrome execution
178
178
  # Avoids Rosetta warnings by directly launching Chrome
@@ -7,6 +7,46 @@ from typing import Optional
7
7
 
8
8
  import platformdirs
9
9
 
10
+ # Application constants
11
+ APP_NAME = "webtap"
12
+ APP_AUTHOR = "webtap"
13
+
14
+ # Directory names
15
+ BIN_DIR_NAME = ".local/bin"
16
+ WRAPPER_NAME = "chrome-debug"
17
+ TMP_RUNTIME_DIR = "/tmp"
18
+
19
+ # Chrome executable names for Linux
20
+ CHROME_NAMES_LINUX = [
21
+ "google-chrome",
22
+ "google-chrome-stable",
23
+ "chromium",
24
+ "chromium-browser",
25
+ ]
26
+
27
+ # Chrome paths for macOS
28
+ CHROME_PATHS_MACOS = [
29
+ "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
30
+ "Applications/Google Chrome.app/Contents/MacOS/Google Chrome", # Relative to home
31
+ ]
32
+
33
+ # Chrome paths for Linux
34
+ CHROME_PATHS_LINUX = [
35
+ "/usr/bin/google-chrome",
36
+ "/usr/bin/google-chrome-stable",
37
+ "/usr/bin/chromium",
38
+ "/usr/bin/chromium-browser",
39
+ "/snap/bin/chromium",
40
+ ]
41
+
42
+ # Platform identifiers
43
+ PLATFORM_DARWIN = "Darwin"
44
+ PLATFORM_LINUX = "Linux"
45
+
46
+ # Application directories
47
+ MACOS_APPLICATIONS_DIR = "Applications"
48
+ LINUX_APPLICATIONS_DIR = ".local/share/applications"
49
+
10
50
 
11
51
  def get_platform_paths() -> dict[str, Path]:
12
52
  """Get platform-appropriate paths using platformdirs.
@@ -14,10 +54,7 @@ def get_platform_paths() -> dict[str, Path]:
14
54
  Returns:
15
55
  Dictionary of paths for config, data, cache, runtime, and state directories.
16
56
  """
17
- app_name = "webtap"
18
- app_author = "webtap"
19
-
20
- dirs = platformdirs.PlatformDirs(app_name, app_author)
57
+ dirs = platformdirs.PlatformDirs(APP_NAME, APP_AUTHOR)
21
58
 
22
59
  paths = {
23
60
  "config_dir": Path(dirs.user_config_dir), # ~/.config/webtap or ~/Library/Application Support/webtap
@@ -31,7 +68,7 @@ def get_platform_paths() -> dict[str, Path]:
31
68
  paths["runtime_dir"] = Path(dirs.user_runtime_dir)
32
69
  except AttributeError:
33
70
  # Fallback for platforms without runtime dir
34
- paths["runtime_dir"] = Path("/tmp") / app_name
71
+ paths["runtime_dir"] = Path(TMP_RUNTIME_DIR) / APP_NAME
35
72
 
36
73
  return paths
37
74
 
@@ -44,21 +81,15 @@ def get_chrome_path() -> Optional[Path]:
44
81
  """
45
82
  system = platform.system()
46
83
 
47
- if system == "Darwin":
84
+ if system == PLATFORM_DARWIN:
48
85
  # macOS standard locations
49
86
  candidates = [
50
- Path("/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"),
51
- Path.home() / "Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
87
+ Path(CHROME_PATHS_MACOS[0]),
88
+ Path.home() / CHROME_PATHS_MACOS[1],
52
89
  ]
53
- elif system == "Linux":
90
+ elif system == PLATFORM_LINUX:
54
91
  # Linux standard locations
55
- candidates = [
56
- Path("/usr/bin/google-chrome"),
57
- Path("/usr/bin/google-chrome-stable"),
58
- Path("/usr/bin/chromium"),
59
- Path("/usr/bin/chromium-browser"),
60
- Path("/snap/bin/chromium"),
61
- ]
92
+ candidates = [Path(p) for p in CHROME_PATHS_LINUX]
62
93
  else:
63
94
  return None
64
95
 
@@ -67,7 +98,7 @@ def get_chrome_path() -> Optional[Path]:
67
98
  return path
68
99
 
69
100
  # Try to find in PATH
70
- for name in ["google-chrome", "google-chrome-stable", "chromium", "chromium-browser"]:
101
+ for name in CHROME_NAMES_LINUX:
71
102
  if found := shutil.which(name):
72
103
  return Path(found)
73
104
 
@@ -84,31 +115,30 @@ def get_platform_info() -> dict:
84
115
  paths = get_platform_paths()
85
116
 
86
117
  # Unified paths for both platforms
87
- paths["bin_dir"] = Path.home() / ".local/bin" # User space, no sudo needed
88
- wrapper_name = "chrome-debug" # Same name on both platforms
118
+ paths["bin_dir"] = Path.home() / BIN_DIR_NAME # User space, no sudo needed
89
119
 
90
120
  # Platform-specific launcher locations
91
- if system == "Darwin":
92
- paths["applications_dir"] = Path.home() / "Applications"
121
+ if system == PLATFORM_DARWIN:
122
+ paths["applications_dir"] = Path.home() / MACOS_APPLICATIONS_DIR
93
123
  else: # Linux
94
- paths["applications_dir"] = Path.home() / ".local/share/applications"
124
+ paths["applications_dir"] = Path.home() / LINUX_APPLICATIONS_DIR
95
125
 
96
126
  chrome_path = get_chrome_path()
97
127
 
98
128
  return {
99
129
  "system": system.lower(),
100
- "is_macos": system == "Darwin",
101
- "is_linux": system == "Linux",
130
+ "is_macos": system == PLATFORM_DARWIN,
131
+ "is_linux": system == PLATFORM_LINUX,
102
132
  "paths": paths,
103
133
  "chrome": {
104
134
  "path": chrome_path,
105
135
  "found": chrome_path is not None,
106
- "wrapper_name": wrapper_name,
136
+ "wrapper_name": WRAPPER_NAME,
107
137
  },
108
138
  "capabilities": {
109
- "desktop_files": system == "Linux",
110
- "app_bundles": system == "Darwin",
111
- "bindfs": system == "Linux" and shutil.which("bindfs") is not None,
139
+ "desktop_files": system == PLATFORM_LINUX,
140
+ "app_bundles": system == PLATFORM_DARWIN,
141
+ "bindfs": system == PLATFORM_LINUX and shutil.which("bindfs") is not None,
112
142
  },
113
143
  }
114
144
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: webtap-tool
3
- Version: 0.2.2
3
+ Version: 0.3.0
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=6sTctXhLKByd8TnKJ99Y4o6xv7AbbPJ37S6YMNsQGBM,1970
3
- webtap/api.py,sha256=mfAqxQfu2lF91jiI6kHQnpmwtwq0Hh9UtuV8ApENXe0,8504
4
- webtap/app.py,sha256=M6-tCT6uvR5aMMYYUymYrXhq4PaUlHVYTv7MDN_svdQ,3246
2
+ webtap/__init__.py,sha256=DFWJGmqZfX8_h4csLA5pKPR4SkaHBMlUgU-WQIE96Gw,1092
3
+ webtap/api.py,sha256=QLfwO_21uSyxBCsqei45c5Uyg7OVfaVopmBncx9ZRfw,8018
4
+ webtap/app.py,sha256=OC8-767GtQ_hAOxUNqD6Yu3JYLNB3ZXdzKn-A1S_RJI,3305
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
@@ -28,6 +28,7 @@ webtap/commands/javascript.py,sha256=QpQdqqoQwwTyz1lpibZ92XKOL89scu_ndgSjkhaYuDk
28
28
  webtap/commands/launch.py,sha256=iZDLundKlxKRLKf3Vz5at42-tp2f-Uj5wZf7fbhBfA0,2202
29
29
  webtap/commands/navigation.py,sha256=Mapawp2AZTJQaws2uwlTgMUhqz7HlVTLxiZ06n_MQc0,6071
30
30
  webtap/commands/network.py,sha256=hwZshGGdVsJ_9MFjOKJXT07I990JjZInw2LLnKXLQ5Y,2910
31
+ webtap/commands/server.py,sha256=LSs3l3Pb_vwmWRnYH-sA9JUPxBTQtRedjFQ4KvDaZK0,6032
31
32
  webtap/commands/setup.py,sha256=dov1LaN50nAEMNIuBLSK7mcnwhfn9rtqdTopBm1-PhA,9648
32
33
  webtap/services/README.md,sha256=rala_jtnNgSiQ1lFLM7x_UQ4SJZDceAm7dpkQMRTYaI,2346
33
34
  webtap/services/__init__.py,sha256=IjFqu0Ak6D-r18aokcQMtenDV3fbelvfjTCejGv6CZ0,570
@@ -36,13 +37,13 @@ webtap/services/console.py,sha256=XVfSKTvEHyyOdujsg85S3wtj1CdZhzKtWwlx25MvSv8,37
36
37
  webtap/services/fetch.py,sha256=nl6bpU2Vnf40kau4-mqAnIkhC-7Lx2vbTJKUglz9KnE,13602
37
38
  webtap/services/main.py,sha256=HcXdPuI7hzsxsNvfN0npGhj_M7HObc83Lr3fuy7BMeE,5673
38
39
  webtap/services/network.py,sha256=0o_--F6YvmXqqFqrcjL1gc6Vr9V1Ytb_U7r_DSUWupA,3444
39
- webtap/services/setup/__init__.py,sha256=rCi6HjyWQmtoBu6NwB1Aw3bEklxsC-bt1jPJ8rGeNgA,6635
40
+ webtap/services/setup/__init__.py,sha256=lfoKCAroc-JoE_r7L-KZkF85ZWiB41MBIgrR7ZISSoE,7157
40
41
  webtap/services/setup/chrome.py,sha256=zfPWeb6zm_xjIfiS2S_O9lR2BjGKaPXXo06pN_B9lAU,7187
41
- webtap/services/setup/desktop.py,sha256=P5bBllQeiHsM2ELbVVmvOxE5k9UiooDh1cRQNKbWm6s,8038
42
+ webtap/services/setup/desktop.py,sha256=fXwQa201W-s2mengm_dJZ9BigJopVrO9YFUQcW_TSFQ,8022
42
43
  webtap/services/setup/extension.py,sha256=OvTLuSi5u-kBAkqWAzfYt5lTNZrduXoCMZhFCuMisew,3318
43
44
  webtap/services/setup/filters.py,sha256=lAPSLMH_KZQO-7bRkmURwzforx7C3SDrKEw2ZogN-Lo,3220
44
- webtap/services/setup/platform.py,sha256=RQrhvp8mLg5Bssy5Slfl5SPVGo3BlUIn3lxVm-ZmkAM,3987
45
- webtap_tool-0.2.2.dist-info/METADATA,sha256=ukRef3zrO-0wrxzGksrDieJ7lBpNNgizETkRIApz_Tg,17588
46
- webtap_tool-0.2.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
47
- webtap_tool-0.2.2.dist-info/entry_points.txt,sha256=iFe575I0CIb1MbfPt0oX2VYyY5gSU_dA551PKVR83TU,39
48
- webtap_tool-0.2.2.dist-info/RECORD,,
45
+ webtap/services/setup/platform.py,sha256=7yn-7LQFffgerWzWRtOG-yNEsR36ICThYUAu_N2FAso,4532
46
+ webtap_tool-0.3.0.dist-info/METADATA,sha256=jm3l2rpT1TBdGU8AU7NJYV7RgwpfzITuPyjh4Zb1_pk,17588
47
+ webtap_tool-0.3.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
48
+ webtap_tool-0.3.0.dist-info/entry_points.txt,sha256=iFe575I0CIb1MbfPt0oX2VYyY5gSU_dA551PKVR83TU,39
49
+ webtap_tool-0.3.0.dist-info/RECORD,,