browser-control-and-automation-cli 0.1.1.dev3__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 (104) hide show
  1. browser_cli/__init__.py +7 -0
  2. browser_cli/actions/__init__.py +5 -0
  3. browser_cli/actions/cli_specs.py +868 -0
  4. browser_cli/agent_scope/__init__.py +14 -0
  5. browser_cli/automation/__init__.py +11 -0
  6. browser_cli/automation/api/__init__.py +5 -0
  7. browser_cli/automation/api/server.py +321 -0
  8. browser_cli/automation/hooks.py +42 -0
  9. browser_cli/automation/loader.py +134 -0
  10. browser_cli/automation/models.py +127 -0
  11. browser_cli/automation/persistence/__init__.py +5 -0
  12. browser_cli/automation/persistence/store.py +682 -0
  13. browser_cli/automation/projections.py +279 -0
  14. browser_cli/automation/publisher.py +153 -0
  15. browser_cli/automation/scheduler/__init__.py +5 -0
  16. browser_cli/automation/scheduler/schedule.py +113 -0
  17. browser_cli/automation/service/__init__.py +8 -0
  18. browser_cli/automation/service/__main__.py +64 -0
  19. browser_cli/automation/service/client.py +232 -0
  20. browser_cli/automation/service/runtime.py +388 -0
  21. browser_cli/automation/toml.py +35 -0
  22. browser_cli/automation/web/__init__.py +5 -0
  23. browser_cli/automation/web/assets.py +377 -0
  24. browser_cli/browser/__init__.py +1 -0
  25. browser_cli/browser/models.py +44 -0
  26. browser_cli/browser/network_capture.py +392 -0
  27. browser_cli/browser/service.py +1519 -0
  28. browser_cli/browser/session.py +158 -0
  29. browser_cli/browser/snapshot.py +35 -0
  30. browser_cli/browser/stealth.py +450 -0
  31. browser_cli/cli/__init__.py +1 -0
  32. browser_cli/cli/error_hints.py +26 -0
  33. browser_cli/cli/main.py +298 -0
  34. browser_cli/commands/__init__.py +1 -0
  35. browser_cli/commands/action.py +25 -0
  36. browser_cli/commands/automation.py +304 -0
  37. browser_cli/commands/doctor.py +336 -0
  38. browser_cli/commands/install_skills.py +138 -0
  39. browser_cli/commands/paths.py +31 -0
  40. browser_cli/commands/read.py +33 -0
  41. browser_cli/commands/reload.py +51 -0
  42. browser_cli/commands/status.py +444 -0
  43. browser_cli/commands/task.py +71 -0
  44. browser_cli/constants.py +97 -0
  45. browser_cli/daemon/__init__.py +1 -0
  46. browser_cli/daemon/__main__.py +34 -0
  47. browser_cli/daemon/app.py +941 -0
  48. browser_cli/daemon/browser_service.py +998 -0
  49. browser_cli/daemon/client.py +280 -0
  50. browser_cli/daemon/models.py +63 -0
  51. browser_cli/daemon/runtime_presentation.py +167 -0
  52. browser_cli/daemon/server.py +103 -0
  53. browser_cli/daemon/state.py +15 -0
  54. browser_cli/daemon/transport.py +77 -0
  55. browser_cli/drivers/__init__.py +6 -0
  56. browser_cli/drivers/_extension/__init__.py +1 -0
  57. browser_cli/drivers/_extension/artifact_actions.py +154 -0
  58. browser_cli/drivers/_extension/dialog_actions.py +35 -0
  59. browser_cli/drivers/_extension/input_actions.py +63 -0
  60. browser_cli/drivers/_extension/locator_actions.py +100 -0
  61. browser_cli/drivers/_extension/observe_actions.py +285 -0
  62. browser_cli/drivers/_extension/page_actions.py +210 -0
  63. browser_cli/drivers/_extension/state_actions.py +134 -0
  64. browser_cli/drivers/base.py +391 -0
  65. browser_cli/drivers/extension_driver.py +33 -0
  66. browser_cli/drivers/models.py +21 -0
  67. browser_cli/drivers/playwright_driver.py +499 -0
  68. browser_cli/error_codes.py +27 -0
  69. browser_cli/errors.py +146 -0
  70. browser_cli/exit_codes.py +9 -0
  71. browser_cli/extension/__init__.py +32 -0
  72. browser_cli/extension/protocol.py +222 -0
  73. browser_cli/extension/session.py +393 -0
  74. browser_cli/network.py +147 -0
  75. browser_cli/outputs/__init__.py +1 -0
  76. browser_cli/outputs/json.py +10 -0
  77. browser_cli/outputs/render.py +7 -0
  78. browser_cli/packaged_skills/__init__.py +1 -0
  79. browser_cli/packaged_skills/browser-cli-converge/SKILL.md +62 -0
  80. browser_cli/packaged_skills/browser-cli-delivery/SKILL.md +61 -0
  81. browser_cli/packaged_skills/browser-cli-explore/SKILL.md +77 -0
  82. browser_cli/profiles/__init__.py +1 -0
  83. browser_cli/profiles/discovery.py +185 -0
  84. browser_cli/refs/__init__.py +17 -0
  85. browser_cli/refs/generator.py +386 -0
  86. browser_cli/refs/models.py +127 -0
  87. browser_cli/refs/registry.py +51 -0
  88. browser_cli/refs/resolver.py +214 -0
  89. browser_cli/tabs/__init__.py +5 -0
  90. browser_cli/tabs/registry.py +283 -0
  91. browser_cli/task_runtime/__init__.py +31 -0
  92. browser_cli/task_runtime/client.py +107 -0
  93. browser_cli/task_runtime/entrypoint.py +110 -0
  94. browser_cli/task_runtime/errors.py +17 -0
  95. browser_cli/task_runtime/flow.py +171 -0
  96. browser_cli/task_runtime/models.py +97 -0
  97. browser_cli/task_runtime/read.py +71 -0
  98. browser_cli/task_runtime/templates.py +58 -0
  99. browser_control_and_automation_cli-0.1.1.dev3.dist-info/METADATA +340 -0
  100. browser_control_and_automation_cli-0.1.1.dev3.dist-info/RECORD +104 -0
  101. browser_control_and_automation_cli-0.1.1.dev3.dist-info/WHEEL +5 -0
  102. browser_control_and_automation_cli-0.1.1.dev3.dist-info/entry_points.txt +2 -0
  103. browser_control_and_automation_cli-0.1.1.dev3.dist-info/licenses/LICENSE +21 -0
  104. browser_control_and_automation_cli-0.1.1.dev3.dist-info/top_level.txt +1 -0
@@ -0,0 +1,391 @@
1
+ """Capability-oriented browser driver base class."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from abc import ABC, abstractmethod
6
+ from typing import Any
7
+
8
+ from browser_cli.refs.models import LocatorSpec, SnapshotInput
9
+
10
+ from .models import DriverHealth, TabState
11
+
12
+
13
+ class BrowserDriver(ABC):
14
+ name: str
15
+
16
+ @abstractmethod
17
+ async def ensure_started(self) -> None: ...
18
+
19
+ @abstractmethod
20
+ async def stop(self) -> dict[str, Any]: ...
21
+
22
+ @abstractmethod
23
+ async def health(self) -> DriverHealth: ...
24
+
25
+ @abstractmethod
26
+ async def new_tab(
27
+ self,
28
+ *,
29
+ page_id: str,
30
+ url: str | None = None,
31
+ wait_until: str = "load",
32
+ timeout_seconds: float | None = None,
33
+ ) -> dict[str, Any]: ...
34
+
35
+ @abstractmethod
36
+ async def close_tab(self, page_id: str) -> dict[str, Any]: ...
37
+
38
+ @abstractmethod
39
+ async def list_tabs(self) -> list[TabState]: ...
40
+
41
+ @abstractmethod
42
+ async def switch_tab(self, page_id: str) -> dict[str, Any]: ...
43
+
44
+ @abstractmethod
45
+ async def get_page_summary(self, page_id: str) -> dict[str, Any]: ...
46
+
47
+ @abstractmethod
48
+ async def get_page_info(self, page_id: str) -> dict[str, Any]: ...
49
+
50
+ @abstractmethod
51
+ async def capture_html(self, page_id: str) -> dict[str, Any]: ...
52
+
53
+ @abstractmethod
54
+ async def capture_snapshot_input(
55
+ self,
56
+ page_id: str,
57
+ *,
58
+ interactive: bool = False,
59
+ full_page: bool = True,
60
+ ) -> SnapshotInput: ...
61
+
62
+ @abstractmethod
63
+ async def navigate(
64
+ self,
65
+ page_id: str,
66
+ url: str,
67
+ *,
68
+ wait_until: str = "load",
69
+ timeout_seconds: float = 30.0,
70
+ ) -> dict[str, Any]: ...
71
+
72
+ @abstractmethod
73
+ async def reload(
74
+ self,
75
+ page_id: str,
76
+ *,
77
+ wait_until: str = "load",
78
+ timeout_seconds: float = 30.0,
79
+ ) -> dict[str, Any]: ...
80
+
81
+ @abstractmethod
82
+ async def go_back(self, page_id: str) -> dict[str, Any]: ...
83
+
84
+ @abstractmethod
85
+ async def go_forward(self, page_id: str) -> dict[str, Any]: ...
86
+
87
+ @abstractmethod
88
+ async def resize(self, page_id: str, *, width: int, height: int) -> dict[str, Any]: ...
89
+
90
+ @abstractmethod
91
+ async def click(self, page_id: str, locator: LocatorSpec) -> dict[str, Any]: ...
92
+
93
+ @abstractmethod
94
+ async def double_click(self, page_id: str, locator: LocatorSpec) -> dict[str, Any]: ...
95
+
96
+ @abstractmethod
97
+ async def hover(self, page_id: str, locator: LocatorSpec) -> dict[str, Any]: ...
98
+
99
+ @abstractmethod
100
+ async def focus(self, page_id: str, locator: LocatorSpec) -> dict[str, Any]: ...
101
+
102
+ @abstractmethod
103
+ async def fill(
104
+ self,
105
+ page_id: str,
106
+ locator: LocatorSpec,
107
+ text: str,
108
+ *,
109
+ submit: bool = False,
110
+ ) -> dict[str, Any]: ...
111
+
112
+ @abstractmethod
113
+ async def select_option(
114
+ self, page_id: str, locator: LocatorSpec, text: str
115
+ ) -> dict[str, Any]: ...
116
+
117
+ @abstractmethod
118
+ async def list_options(self, page_id: str, locator: LocatorSpec) -> dict[str, Any]: ...
119
+
120
+ @abstractmethod
121
+ async def check(
122
+ self, page_id: str, locator: LocatorSpec, *, checked: bool
123
+ ) -> dict[str, Any]: ...
124
+
125
+ @abstractmethod
126
+ async def scroll_to(self, page_id: str, locator: LocatorSpec) -> dict[str, Any]: ...
127
+
128
+ @abstractmethod
129
+ async def drag(
130
+ self, page_id: str, start_locator: LocatorSpec, end_locator: LocatorSpec
131
+ ) -> dict[str, Any]: ...
132
+
133
+ @abstractmethod
134
+ async def upload(
135
+ self, page_id: str, locator: LocatorSpec, file_path: str
136
+ ) -> dict[str, Any]: ...
137
+
138
+ @abstractmethod
139
+ async def evaluate(self, page_id: str, code: str) -> dict[str, Any]: ...
140
+
141
+ @abstractmethod
142
+ async def evaluate_on(
143
+ self, page_id: str, locator: LocatorSpec, code: str
144
+ ) -> dict[str, Any]: ...
145
+
146
+ @abstractmethod
147
+ async def wait(
148
+ self,
149
+ page_id: str,
150
+ *,
151
+ seconds: float | None = None,
152
+ text: str | None = None,
153
+ gone: bool = False,
154
+ exact: bool = False,
155
+ ) -> dict[str, Any]: ...
156
+
157
+ @abstractmethod
158
+ async def wait_for_network_idle(
159
+ self, page_id: str, *, timeout_seconds: float = 30.0
160
+ ) -> dict[str, Any]: ...
161
+
162
+ @abstractmethod
163
+ async def start_console_capture(self, page_id: str) -> dict[str, Any]: ...
164
+
165
+ @abstractmethod
166
+ async def get_console_messages(
167
+ self,
168
+ page_id: str,
169
+ *,
170
+ message_type: str | None = None,
171
+ clear: bool = True,
172
+ ) -> dict[str, Any]: ...
173
+
174
+ @abstractmethod
175
+ async def stop_console_capture(self, page_id: str) -> dict[str, Any]: ...
176
+
177
+ @abstractmethod
178
+ async def start_network_capture(self, page_id: str) -> dict[str, Any]: ...
179
+
180
+ @abstractmethod
181
+ async def wait_for_network_record(
182
+ self,
183
+ page_id: str,
184
+ *,
185
+ url_contains: str | None = None,
186
+ url_regex: str | None = None,
187
+ method: str | None = None,
188
+ status: int | None = None,
189
+ resource_type: str | None = None,
190
+ mime_contains: str | None = None,
191
+ include_static: bool = False,
192
+ timeout_seconds: float = 30.0,
193
+ ) -> dict[str, Any]: ...
194
+
195
+ @abstractmethod
196
+ async def get_network_records(
197
+ self,
198
+ page_id: str,
199
+ *,
200
+ url_contains: str | None = None,
201
+ url_regex: str | None = None,
202
+ method: str | None = None,
203
+ status: int | None = None,
204
+ resource_type: str | None = None,
205
+ mime_contains: str | None = None,
206
+ include_static: bool = False,
207
+ clear: bool = True,
208
+ ) -> dict[str, Any]: ...
209
+
210
+ @abstractmethod
211
+ async def stop_network_capture(self, page_id: str) -> dict[str, Any]: ...
212
+
213
+ @abstractmethod
214
+ async def get_cookies(
215
+ self,
216
+ page_id: str,
217
+ *,
218
+ name: str | None = None,
219
+ domain: str | None = None,
220
+ path: str | None = None,
221
+ ) -> dict[str, Any]: ...
222
+
223
+ @abstractmethod
224
+ async def set_cookie(
225
+ self,
226
+ page_id: str,
227
+ *,
228
+ name: str,
229
+ value: str,
230
+ domain: str | None = None,
231
+ path: str = "/",
232
+ expires: float | None = None,
233
+ http_only: bool = False,
234
+ secure: bool = False,
235
+ same_site: str | None = None,
236
+ ) -> dict[str, Any]: ...
237
+
238
+ @abstractmethod
239
+ async def clear_cookies(
240
+ self,
241
+ page_id: str,
242
+ *,
243
+ name: str | None = None,
244
+ domain: str | None = None,
245
+ path: str | None = None,
246
+ ) -> dict[str, Any]: ...
247
+
248
+ @abstractmethod
249
+ async def save_storage_state(
250
+ self, page_id: str, *, path: str | None = None
251
+ ) -> dict[str, Any]: ...
252
+
253
+ @abstractmethod
254
+ async def load_storage_state(self, page_id: str, *, path: str) -> dict[str, Any]: ...
255
+
256
+ @abstractmethod
257
+ async def verify_text(
258
+ self,
259
+ page_id: str,
260
+ *,
261
+ text: str,
262
+ exact: bool = False,
263
+ timeout_seconds: float = 5.0,
264
+ ) -> dict[str, Any]: ...
265
+
266
+ @abstractmethod
267
+ async def verify_url(
268
+ self, page_id: str, *, expected: str, exact: bool = False
269
+ ) -> dict[str, Any]: ...
270
+
271
+ @abstractmethod
272
+ async def verify_title(
273
+ self, page_id: str, *, expected: str, exact: bool = False
274
+ ) -> dict[str, Any]: ...
275
+
276
+ @abstractmethod
277
+ async def verify_visible(
278
+ self,
279
+ page_id: str,
280
+ *,
281
+ role: str,
282
+ name: str,
283
+ timeout_seconds: float = 5.0,
284
+ ) -> dict[str, Any]: ...
285
+
286
+ @abstractmethod
287
+ async def verify_state(
288
+ self, page_id: str, *, locator: LocatorSpec, state: str
289
+ ) -> dict[str, Any]: ...
290
+
291
+ @abstractmethod
292
+ async def verify_value(
293
+ self, page_id: str, *, locator: LocatorSpec, expected: str
294
+ ) -> dict[str, Any]: ...
295
+
296
+ @abstractmethod
297
+ async def type_text(
298
+ self, page_id: str, text: str, *, submit: bool = False
299
+ ) -> dict[str, Any]: ...
300
+
301
+ @abstractmethod
302
+ async def press_key(self, page_id: str, key: str) -> dict[str, Any]: ...
303
+
304
+ @abstractmethod
305
+ async def key_down(self, page_id: str, key: str) -> dict[str, Any]: ...
306
+
307
+ @abstractmethod
308
+ async def key_up(self, page_id: str, key: str) -> dict[str, Any]: ...
309
+
310
+ @abstractmethod
311
+ async def wheel(self, page_id: str, *, dx: int = 0, dy: int = 700) -> dict[str, Any]: ...
312
+
313
+ @abstractmethod
314
+ async def mouse_move(self, page_id: str, *, x: int, y: int) -> dict[str, Any]: ...
315
+
316
+ @abstractmethod
317
+ async def mouse_click(
318
+ self,
319
+ page_id: str,
320
+ *,
321
+ x: int,
322
+ y: int,
323
+ button: str = "left",
324
+ count: int = 1,
325
+ ) -> dict[str, Any]: ...
326
+
327
+ @abstractmethod
328
+ async def mouse_drag(
329
+ self, page_id: str, *, x1: int, y1: int, x2: int, y2: int
330
+ ) -> dict[str, Any]: ...
331
+
332
+ @abstractmethod
333
+ async def mouse_down(self, page_id: str, *, button: str = "left") -> dict[str, Any]: ...
334
+
335
+ @abstractmethod
336
+ async def mouse_up(self, page_id: str, *, button: str = "left") -> dict[str, Any]: ...
337
+
338
+ @abstractmethod
339
+ async def screenshot(
340
+ self, page_id: str, *, path: str, full_page: bool = False
341
+ ) -> dict[str, Any]: ...
342
+
343
+ @abstractmethod
344
+ async def save_pdf(self, page_id: str, *, path: str) -> dict[str, Any]: ...
345
+
346
+ @abstractmethod
347
+ async def setup_dialog_handler(
348
+ self,
349
+ page_id: str,
350
+ *,
351
+ default_action: str = "accept",
352
+ default_prompt_text: str | None = None,
353
+ ) -> dict[str, Any]: ...
354
+
355
+ @abstractmethod
356
+ async def handle_dialog(
357
+ self,
358
+ page_id: str,
359
+ *,
360
+ accept: bool,
361
+ prompt_text: str | None = None,
362
+ ) -> dict[str, Any]: ...
363
+
364
+ @abstractmethod
365
+ async def remove_dialog_handler(self, page_id: str) -> dict[str, Any]: ...
366
+
367
+ @abstractmethod
368
+ async def start_tracing(
369
+ self,
370
+ page_id: str,
371
+ *,
372
+ screenshots: bool = True,
373
+ snapshots: bool = True,
374
+ sources: bool = False,
375
+ ) -> dict[str, Any]: ...
376
+
377
+ @abstractmethod
378
+ async def add_trace_chunk(
379
+ self, page_id: str, *, title: str | None = None
380
+ ) -> dict[str, Any]: ...
381
+
382
+ @abstractmethod
383
+ async def stop_tracing(self, page_id: str, *, path: str | None = None) -> dict[str, Any]: ...
384
+
385
+ @abstractmethod
386
+ async def start_video(
387
+ self, page_id: str, *, width: int | None = None, height: int | None = None
388
+ ) -> dict[str, Any]: ...
389
+
390
+ @abstractmethod
391
+ async def stop_video(self, page_id: str, *, path: str | None = None) -> dict[str, Any]: ...
@@ -0,0 +1,33 @@
1
+ """Real-Chrome driver backed by the Browser CLI extension session."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from browser_cli.extension import ExtensionHub
6
+
7
+ from ._extension.artifact_actions import ExtensionDriverArtifactActionsMixin
8
+ from ._extension.dialog_actions import ExtensionDriverDialogActionsMixin
9
+ from ._extension.input_actions import ExtensionDriverInputActionsMixin
10
+ from ._extension.locator_actions import ExtensionDriverLocatorActionsMixin
11
+ from ._extension.observe_actions import ExtensionDriverObserveActionsMixin
12
+ from ._extension.page_actions import ExtensionDriverPageActionsMixin
13
+ from ._extension.state_actions import ExtensionDriverStateMixin
14
+ from .base import BrowserDriver
15
+
16
+
17
+ class ExtensionDriver(
18
+ ExtensionDriverArtifactActionsMixin,
19
+ ExtensionDriverDialogActionsMixin,
20
+ ExtensionDriverInputActionsMixin,
21
+ ExtensionDriverObserveActionsMixin,
22
+ ExtensionDriverLocatorActionsMixin,
23
+ ExtensionDriverPageActionsMixin,
24
+ ExtensionDriverStateMixin,
25
+ BrowserDriver,
26
+ ):
27
+ name = "extension"
28
+
29
+ def __init__(self, hub: ExtensionHub) -> None:
30
+ self._hub = hub
31
+ self._page_to_tab: dict[str, int] = {}
32
+ self._tab_to_page: dict[int, str] = {}
33
+ self._active_page_id: str | None = None
@@ -0,0 +1,21 @@
1
+ """Shared driver-side dataclasses."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass, field
6
+ from typing import Any
7
+
8
+
9
+ @dataclass(slots=True, frozen=True)
10
+ class TabState:
11
+ page_id: str
12
+ url: str
13
+ title: str = ""
14
+ active: bool = False
15
+
16
+
17
+ @dataclass(slots=True, frozen=True)
18
+ class DriverHealth:
19
+ name: str
20
+ available: bool
21
+ details: dict[str, Any] = field(default_factory=dict)