browserwright 0.6.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.
Files changed (98) hide show
  1. browserwright/__init__.py +33 -0
  2. browserwright/__main__.py +6 -0
  3. browserwright/_executor/__init__.py +47 -0
  4. browserwright/_executor/__main__.py +9 -0
  5. browserwright/_executor/client.py +127 -0
  6. browserwright/_executor/process.py +652 -0
  7. browserwright/_executor/protocol.py +152 -0
  8. browserwright/api.py +66 -0
  9. browserwright/cdp.py +285 -0
  10. browserwright/cli.py +741 -0
  11. browserwright/daemon/__init__.py +8 -0
  12. browserwright/daemon/_ipc.py +444 -0
  13. browserwright/daemon/active_tab.py +183 -0
  14. browserwright/daemon/auth.py +395 -0
  15. browserwright/daemon/backends/__init__.py +59 -0
  16. browserwright/daemon/backends/base.py +120 -0
  17. browserwright/daemon/backends/cloud.py +222 -0
  18. browserwright/daemon/backends/env.py +119 -0
  19. browserwright/daemon/backends/extension.py +185 -0
  20. browserwright/daemon/backends/rdp.py +214 -0
  21. browserwright/daemon/cli.py +1437 -0
  22. browserwright/daemon/config.py +380 -0
  23. browserwright/daemon/doctor.py +179 -0
  24. browserwright/daemon/errors.py +34 -0
  25. browserwright/daemon/launch_chrome.py +353 -0
  26. browserwright/daemon/observability.py +181 -0
  27. browserwright/daemon/platforms.py +234 -0
  28. browserwright/daemon/resolver.py +72 -0
  29. browserwright/daemon/server/__init__.py +6 -0
  30. browserwright/daemon/server/daemon.py +229 -0
  31. browserwright/daemon/server/executor_registry.py +434 -0
  32. browserwright/daemon/server/extension_upstream.py +677 -0
  33. browserwright/daemon/server/facade.py +375 -0
  34. browserwright/daemon/server/facade_extension.py +969 -0
  35. browserwright/daemon/server/listener.py +1058 -0
  36. browserwright/daemon/server/proxy.py +1991 -0
  37. browserwright/daemon/server/relay.py +783 -0
  38. browserwright/daemon/server/state.py +432 -0
  39. browserwright/daemon/server/upstream.py +266 -0
  40. browserwright/daemon/userscripts.py +150 -0
  41. browserwright/discovery.py +213 -0
  42. browserwright/errors.py +177 -0
  43. browserwright/health.py +169 -0
  44. browserwright/install.py +628 -0
  45. browserwright/memory/__init__.py +15 -0
  46. browserwright/memory/_md.py +120 -0
  47. browserwright/memory/_yaml.py +217 -0
  48. browserwright/memory/global_mem.py +201 -0
  49. browserwright/memory/repl_mem.py +28 -0
  50. browserwright/memory/session_decisions.py +53 -0
  51. browserwright/memory/site_mem.py +381 -0
  52. browserwright/mode_b_client.py +590 -0
  53. browserwright/multitask.py +131 -0
  54. browserwright/output_schema.py +99 -0
  55. browserwright/primitives/__init__.py +67 -0
  56. browserwright/primitives/discovery_api.py +79 -0
  57. browserwright/primitives/http.py +42 -0
  58. browserwright/primitives/inspect.py +876 -0
  59. browserwright/primitives/interact.py +518 -0
  60. browserwright/primitives/page.py +556 -0
  61. browserwright/primitives/site.py +143 -0
  62. browserwright/release_install.py +466 -0
  63. browserwright/repl/__init__.py +6 -0
  64. browserwright/repl/_namespace.py +106 -0
  65. browserwright/repl/_smart_goto.py +236 -0
  66. browserwright/repl/inline.py +180 -0
  67. browserwright/repl/playwright_handle.py +449 -0
  68. browserwright/repl/snapshot.py +150 -0
  69. browserwright/session.py +229 -0
  70. browserwright/session_create.py +252 -0
  71. browserwright/session_ctx.py +24 -0
  72. browserwright/session_registry.py +133 -0
  73. browserwright/session_runtime.py +133 -0
  74. browserwright/site_skills_starter/github.com/SKILL.md +14 -0
  75. browserwright/site_skills_starter/github.com/memory.md +29 -0
  76. browserwright/site_skills_starter/github.com/tasks/list_issues.py +55 -0
  77. browserwright/site_skills_starter/google.com/SKILL.md +16 -0
  78. browserwright/site_skills_starter/google.com/memory.md +27 -0
  79. browserwright/site_skills_starter/google.com/tasks/search.py +53 -0
  80. browserwright/site_skills_starter/producthunt.com/SKILL.md +7 -0
  81. browserwright/site_skills_starter/producthunt.com/memory.md +26 -0
  82. browserwright/site_skills_starter/producthunt.com/tasks/today.py +64 -0
  83. browserwright/site_skills_starter/wikipedia.org/SKILL.md +7 -0
  84. browserwright/site_skills_starter/wikipedia.org/memory.md +22 -0
  85. browserwright/site_skills_starter/wikipedia.org/tasks/lookup.py +55 -0
  86. browserwright/site_skills_starter/ycombinator.com/SKILL.md +8 -0
  87. browserwright/site_skills_starter/ycombinator.com/memory.md +25 -0
  88. browserwright/site_skills_starter/ycombinator.com/tasks/front_page.py +63 -0
  89. browserwright/skill_doc.py +140 -0
  90. browserwright/skill_runtime.md +194 -0
  91. browserwright/subscriptions.py +213 -0
  92. browserwright/task_runner.py +125 -0
  93. browserwright/version.py +117 -0
  94. browserwright-0.6.2.dist-info/METADATA +12 -0
  95. browserwright-0.6.2.dist-info/RECORD +98 -0
  96. browserwright-0.6.2.dist-info/WHEEL +5 -0
  97. browserwright-0.6.2.dist-info/entry_points.txt +3 -0
  98. browserwright-0.6.2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,169 @@
1
+ """Skill-side health: forward ``browserwright-daemon doctor`` and derive an
2
+ actionable ``{status, message, fix}`` check table (A4).
3
+
4
+ This is **not** a CDP driving path — it shells out to the daemon's standalone
5
+ ``doctor`` subcommand (zero ws side effects, spec H3) and transforms the blob.
6
+ It lived on the old Mode A ``DaemonClient`` historically; it has no dependency
7
+ on Mode A and stays after Mode A's removal. Consumed by ``browserwright doctor``
8
+ (``cli.py``) and the install wizard's option-availability probe (``install.py``).
9
+ """
10
+ from __future__ import annotations
11
+
12
+ import json
13
+ import subprocess
14
+
15
+ # Doctor blobs this browserwright build knows how to read. The daemon's current
16
+ # contract is v2 (bumped in daemon v0.5.3); v1 is still parseable for the fields
17
+ # we use. Anything else = real version skew.
18
+ _SUPPORTED_DOCTOR_SCHEMAS = (1, 2)
19
+
20
+
21
+ def daemon_doctor() -> dict:
22
+ """Forward ``browserwright-daemon doctor --json``. Always returns a dict; on
23
+ failure returns a synthetic ``schema_version:1`` blob explaining why."""
24
+ cmd = ["browserwright-daemon", "doctor", "--json"]
25
+ try:
26
+ proc = subprocess.run(cmd, capture_output=True, text=True, timeout=10)
27
+ except (FileNotFoundError, subprocess.TimeoutExpired) as e:
28
+ return {
29
+ "schema_version": 1,
30
+ "backends": [],
31
+ "error": str(e),
32
+ "skill_synthetic": True,
33
+ }
34
+ if proc.returncode != 0:
35
+ return {
36
+ "schema_version": 1,
37
+ "backends": [],
38
+ "error": (proc.stderr or proc.stdout or "").strip(),
39
+ "skill_synthetic": True,
40
+ "exit_code": proc.returncode,
41
+ }
42
+ try:
43
+ return json.loads(proc.stdout)
44
+ except json.JSONDecodeError:
45
+ return {
46
+ "schema_version": 1,
47
+ "backends": [],
48
+ "error": "doctor output was not JSON",
49
+ "skill_synthetic": True,
50
+ }
51
+
52
+
53
+ def doctor_checks() -> dict:
54
+ """Derive an actionable ``{status, message, fix}`` check table from the raw
55
+ ``daemon_doctor()`` blob (A4).
56
+
57
+ Each check is ``{"name", "status", "message", "fix"}`` where status is one
58
+ of ``pass`` / ``warn`` / ``fail``. The discipline (enforced by the gate
59
+ test): **every ``fail`` check carries a non-empty ``fix``**. The ``fix`` for
60
+ non-fail checks is the empty string.
61
+
62
+ This is a pure transform over the daemon blob plus a couple of local probes
63
+ (helper-module parse), so it stays deterministic and testable without a live
64
+ browser. Checks whose ground truth needs a live daemon / extension degrade
65
+ to ``warn`` rather than asserting health they can't observe.
66
+ """
67
+ info = daemon_doctor()
68
+ checks: list[dict] = []
69
+
70
+ def add(name, status, message, fix=""):
71
+ # Invariant: a fail must always ship a recovery action.
72
+ if status == "fail" and not (fix and fix.strip()):
73
+ fix = "run `browserwright doctor` and address the first failing check"
74
+ checks.append({"name": name, "status": status,
75
+ "message": message, "fix": fix})
76
+
77
+ # 1. daemon reachable (did `browserwright-daemon doctor` actually answer?)
78
+ if info.get("skill_synthetic"):
79
+ add(
80
+ "daemon",
81
+ "fail",
82
+ info.get("error") or "browserwright-daemon did not respond",
83
+ "install/start the daemon: ensure `browserwright-daemon` is on PATH "
84
+ "then `browserwright-daemon serve`",
85
+ )
86
+ else:
87
+ add("daemon", "pass", "browserwright-daemon responded to doctor", "")
88
+
89
+ # 2. schema version sanity (catches a daemon too old to speak the blob)
90
+ sv = info.get("schema_version")
91
+ if not info.get("skill_synthetic"):
92
+ if sv in _SUPPORTED_DOCTOR_SCHEMAS:
93
+ add("daemon_schema", "pass", f"doctor schema_version={sv}", "")
94
+ else:
95
+ add(
96
+ "daemon_schema",
97
+ "warn",
98
+ f"unexpected doctor schema_version={sv!r}",
99
+ "update browserwright-daemon and browserwright to matching versions",
100
+ )
101
+
102
+ # 3. at least one usable backend (relay/extension/rdp connection probe)
103
+ backends = info.get("backends") or []
104
+ usable = [b for b in backends if b.get("available")]
105
+ if not info.get("skill_synthetic"):
106
+ if usable:
107
+ names = ", ".join(b.get("name", "?") for b in usable)
108
+ add("backend", "pass", f"available backend(s): {names}", "")
109
+ elif backends:
110
+ # backends exist but none available — surface each one's hint.
111
+ hints = [b.get("needs_user_action") for b in backends
112
+ if b.get("needs_user_action")]
113
+ add(
114
+ "backend",
115
+ "fail",
116
+ "no backend is available "
117
+ f"(saw: {', '.join(b.get('name', '?') for b in backends)})",
118
+ "; ".join(hints) if hints else
119
+ "connect the extension (load unpacked) or start an rdp Chrome, "
120
+ "then re-run doctor",
121
+ )
122
+ else:
123
+ add(
124
+ "backend",
125
+ "fail",
126
+ "daemon reported no backends",
127
+ "start a backend: load the extension or "
128
+ "create an rdp session after `browserwright-daemon serve`",
129
+ )
130
+
131
+ # 4. extension/relay specific: if an extension backend exists but is
132
+ # unavailable, call it out as its own actionable check.
133
+ ext = next((b for b in backends if b.get("name") == "extension"), None)
134
+ if ext is not None:
135
+ if ext.get("available"):
136
+ add("extension", "pass",
137
+ f"extension connected (ws={ext.get('ws_url', '')})", "")
138
+ else:
139
+ add(
140
+ "extension",
141
+ "warn",
142
+ ext.get("ux_warning") or "extension backend present but not connected",
143
+ ext.get("needs_user_action")
144
+ or "open Chrome and load the unpacked extension, then re-run doctor",
145
+ )
146
+
147
+ # 5. helper surface parses (local, deterministic): can we import the
148
+ # primitive surface agents actually call? A broken install / syntax
149
+ # error here would otherwise only show up mid-task.
150
+ try:
151
+ from . import api as _api # noqa: F401
152
+ n = len(getattr(_api, "EXPORTS", []) or [])
153
+ add("helpers", "pass", f"helper surface imports ({n} exports)", "")
154
+ except Exception as e: # noqa: BLE001
155
+ add(
156
+ "helpers",
157
+ "fail",
158
+ f"helper surface failed to import: {e!r}",
159
+ "reinstall browserwright (`browserwright install`) or check the "
160
+ "traceback above for a syntax/dependency error",
161
+ )
162
+
163
+ any_fail = any(c["status"] == "fail" for c in checks)
164
+ return {
165
+ "schema_version": 1,
166
+ "ok": not any_fail,
167
+ "checks": checks,
168
+ "raw": info,
169
+ }