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

@@ -15,26 +15,39 @@ mcp_desc = get_mcp_description("js")
15
15
  },
16
16
  fastmcp={"type": "tool", "description": mcp_desc} if mcp_desc else {"type": "tool"},
17
17
  )
18
- def js(state, code: str, selection: int = None, wait_return: bool = True, await_promise: bool = False) -> dict: # pyright: ignore[reportArgumentType]
18
+ def js(
19
+ state,
20
+ code: str,
21
+ selection: int = None, # pyright: ignore[reportArgumentType]
22
+ persist: bool = False,
23
+ wait_return: bool = True,
24
+ await_promise: bool = False,
25
+ ) -> dict:
19
26
  """Execute JavaScript in the browser with optional element selection.
20
27
 
21
28
  Args:
22
29
  code: JavaScript code to execute (use 'element' variable if selection provided)
23
30
  selection: Browser element selection number (e.g., 1 for #1) - makes element available
31
+ persist: Keep variables in global scope across calls (default: False, uses fresh scope)
24
32
  wait_return: Wait for and return result (default: True)
25
33
  await_promise: Await promises before returning (default: False)
26
34
 
27
35
  Examples:
36
+ # Default: fresh scope (no redeclaration errors)
37
+ js("const x = 1") # ✓ x isolated
38
+ js("const x = 2") # ✓ No error, fresh scope
28
39
  js("document.title") # Get page title
29
- js("document.body.innerText.length") # Get text length
30
- js("console.log('test')", wait_return=False) # Fire and forget
31
40
  js("[...document.links].map(a => a.href)") # Get all links
32
41
 
33
- # With browser element selection
34
- js("element.offsetWidth", selection=1) # Use element #1 from browser()
42
+ # With browser element selection (always fresh scope)
43
+ js("element.offsetWidth", selection=1) # Use element #1
35
44
  js("element.classList", selection=2) # Use element #2
36
45
  js("element.getBoundingClientRect()", selection=1)
37
46
 
47
+ # Persistent scope: keep variables across calls
48
+ js("var data = fetch('/api')", persist=True) # data persists
49
+ js("data.json()", persist=True) # Access data from previous call
50
+
38
51
  # Async operations
39
52
  js("fetch('/api').then(r => r.json())", await_promise=True)
40
53
 
@@ -74,8 +87,13 @@ def js(state, code: str, selection: int = None, wait_return: bool = True, await_
74
87
  if not js_path:
75
88
  return error_response(f"Selection #{selection} has no jsPath")
76
89
 
77
- # Wrap code with element variable
78
- code = f"const element = {js_path}; {code}"
90
+ # Wrap code with element variable in fresh scope (IIFE)
91
+ # Selection always uses fresh scope to avoid element redeclaration errors
92
+ code = f"(() => {{ const element = {js_path}; return ({code}); }})()"
93
+ elif not persist:
94
+ # Default: wrap in IIFE for fresh scope (avoids const/let redeclaration errors)
95
+ code = f"(() => {{ return ({code}); }})()"
96
+ # else: persist=True, use code as-is (global scope)
79
97
 
80
98
  result = state.cdp.execute(
81
99
  "Runtime.evaluate", {"expression": code, "returnByValue": wait_return, "awaitPromise": await_promise}
@@ -38,8 +38,8 @@ def selections(state, expr: str = None) -> dict: # pyright: ignore[reportArgume
38
38
  "No browser selections available",
39
39
  suggestions=[
40
40
  "Use the Chrome extension to select elements",
41
- "Click 'Start Selection Mode' in the extension popup",
42
- "Select elements on the page and submit a prompt",
41
+ "Click 'Start Selection Mode' in the extension side panel",
42
+ "Select elements on the page",
43
43
  ],
44
44
  )
45
45
 
@@ -12,7 +12,7 @@ logger = logging.getLogger(__name__)
12
12
 
13
13
  # GitHub URLs for extension files
14
14
  EXTENSION_BASE_URL = "https://raw.githubusercontent.com/angelsen/tap-tools/main/packages/webtap/extension"
15
- EXTENSION_FILES = ["manifest.json", "popup.html", "popup.js"]
15
+ EXTENSION_FILES = ["manifest.json", "content.js", "sidepanel.html", "sidepanel.js"]
16
16
 
17
17
 
18
18
  class ExtensionSetupService:
@@ -46,6 +46,13 @@ class ExtensionSetupService:
46
46
  # Ensure base directories exist
47
47
  ensure_directories()
48
48
 
49
+ # If force, clean out old extension files first
50
+ if force and self.extension_dir.exists():
51
+ import shutil
52
+
53
+ shutil.rmtree(self.extension_dir)
54
+ logger.info(f"Cleaned old extension directory: {self.extension_dir}")
55
+
49
56
  # Create extension directory
50
57
  self.extension_dir.mkdir(parents=True, exist_ok=True)
51
58
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: webtap-tool
3
- Version: 0.5.0
3
+ Version: 0.5.2
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
@@ -23,11 +23,11 @@ webtap/commands/events.py,sha256=dsS6xd8GfkZ4VOnAQSCMxyEvwdha9J0Kh9oeK0CaU5Y,405
23
23
  webtap/commands/fetch.py,sha256=8J6TPBWhStbkN5c5Q4KmK6nB5WiIgnAk0BkPFbh9ggg,7737
24
24
  webtap/commands/filters.py,sha256=jDZ8JcYIZv_K6aupwuAo9uqAi85e3EIKbf38BXz5nnI,10316
25
25
  webtap/commands/inspect.py,sha256=QonZigFYnfEVWYQY__r0n1aVvTqFBukFV-AWzc5KmfA,5711
26
- webtap/commands/javascript.py,sha256=9n4gOA7cjFjCL_p1cePRS1j7WZRV771MwADZeC5g66s,4098
26
+ webtap/commands/javascript.py,sha256=j0gKl6Y6-TWBYuN8SjoRHFPOhns9C1h8NkpIQkhRXG0,4879
27
27
  webtap/commands/launch.py,sha256=iZDLundKlxKRLKf3Vz5at42-tp2f-Uj5wZf7fbhBfA0,2202
28
28
  webtap/commands/navigation.py,sha256=aRVW-t2YJ0Haf6Wkg7uq8GstiRftklop9W1TicUk3oo,6036
29
29
  webtap/commands/network.py,sha256=gEOg_u7VF9A5aKv5myzLCuvfAUkF1OPxsuj4UAgbS44,3111
30
- webtap/commands/selections.py,sha256=uyEET9eaKcLWjBz0QUdMRuRU-HIBXGtARxK6k71zOMY,4910
30
+ webtap/commands/selections.py,sha256=M001d_Gc51aSTuVeXGa19LDh2ZGR_qBJEjVGKpcGGFM,4895
31
31
  webtap/commands/server.py,sha256=DOcIgYuKp0ydwrK9EA3hGwqOwfwM9DABhdPu3hk_jjo,6948
32
32
  webtap/commands/setup.py,sha256=dov1LaN50nAEMNIuBLSK7mcnwhfn9rtqdTopBm1-PhA,9648
33
33
  webtap/services/README.md,sha256=rala_jtnNgSiQ1lFLM7x_UQ4SJZDceAm7dpkQMRTYaI,2346
@@ -41,10 +41,10 @@ webtap/services/network.py,sha256=0o_--F6YvmXqqFqrcjL1gc6Vr9V1Ytb_U7r_DSUWupA,34
41
41
  webtap/services/setup/__init__.py,sha256=lfoKCAroc-JoE_r7L-KZkF85ZWiB41MBIgrR7ZISSoE,7157
42
42
  webtap/services/setup/chrome.py,sha256=zfPWeb6zm_xjIfiS2S_O9lR2BjGKaPXXo06pN_B9lAU,7187
43
43
  webtap/services/setup/desktop.py,sha256=fXwQa201W-s2mengm_dJZ9BigJopVrO9YFUQcW_TSFQ,8022
44
- webtap/services/setup/extension.py,sha256=OvTLuSi5u-kBAkqWAzfYt5lTNZrduXoCMZhFCuMisew,3318
44
+ webtap/services/setup/extension.py,sha256=iJY43JlQO6Vicgd9Mz6Mw0LQfbBNUGhnwI8n-LnvHBY,3602
45
45
  webtap/services/setup/filters.py,sha256=lAPSLMH_KZQO-7bRkmURwzforx7C3SDrKEw2ZogN-Lo,3220
46
46
  webtap/services/setup/platform.py,sha256=7yn-7LQFffgerWzWRtOG-yNEsR36ICThYUAu_N2FAso,4532
47
- webtap_tool-0.5.0.dist-info/METADATA,sha256=qRqF6_yp9fLVO_c57vgBkKpvC-wLGhVrpWaMMMWwJXU,17588
48
- webtap_tool-0.5.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
49
- webtap_tool-0.5.0.dist-info/entry_points.txt,sha256=iFe575I0CIb1MbfPt0oX2VYyY5gSU_dA551PKVR83TU,39
50
- webtap_tool-0.5.0.dist-info/RECORD,,
47
+ webtap_tool-0.5.2.dist-info/METADATA,sha256=Tcq1QufQPMu8KhNGAOnV0UIc6_y1jiXag6Oe0yuipgE,17588
48
+ webtap_tool-0.5.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
49
+ webtap_tool-0.5.2.dist-info/entry_points.txt,sha256=iFe575I0CIb1MbfPt0oX2VYyY5gSU_dA551PKVR83TU,39
50
+ webtap_tool-0.5.2.dist-info/RECORD,,