code-puppy 0.0.177__py3-none-any.whl → 0.0.179__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.
@@ -1,552 +0,0 @@
1
- """Browser element interaction tools for clicking, typing, and form manipulation."""
2
-
3
- from typing import Any, Dict, List, Optional
4
-
5
- from pydantic_ai import RunContext
6
-
7
- from code_puppy.messaging import emit_info
8
- from code_puppy.tools.common import generate_group_id
9
-
10
- from .camoufox_manager import get_camoufox_manager
11
-
12
-
13
- async def click_element(
14
- selector: str,
15
- timeout: int = 10000,
16
- force: bool = False,
17
- button: str = "left",
18
- modifiers: Optional[List[str]] = None,
19
- ) -> Dict[str, Any]:
20
- """Click on an element."""
21
- group_id = generate_group_id("browser_click", selector[:100])
22
- emit_info(
23
- f"[bold white on blue] BROWSER CLICK [/bold white on blue] 🖱️ selector='{selector}' button={button}",
24
- message_group=group_id,
25
- )
26
- try:
27
- browser_manager = get_camoufox_manager()
28
- page = await browser_manager.get_current_page()
29
-
30
- if not page:
31
- return {"success": False, "error": "No active browser page available"}
32
-
33
- # Find element
34
- element = page.locator(selector)
35
-
36
- # Wait for element to be visible and enabled
37
- await element.wait_for(state="visible", timeout=timeout)
38
-
39
- # Click options
40
- click_options = {
41
- "force": force,
42
- "button": button,
43
- "timeout": timeout,
44
- }
45
-
46
- if modifiers:
47
- click_options["modifiers"] = modifiers
48
-
49
- await element.click(**click_options)
50
-
51
- emit_info(f"[green]Clicked element: {selector}[/green]", message_group=group_id)
52
-
53
- return {"success": True, "selector": selector, "action": f"{button}_click"}
54
-
55
- except Exception as e:
56
- emit_info(f"[red]Click failed: {str(e)}[/red]", message_group=group_id)
57
- return {"success": False, "error": str(e), "selector": selector}
58
-
59
-
60
- async def double_click_element(
61
- selector: str,
62
- timeout: int = 10000,
63
- force: bool = False,
64
- ) -> Dict[str, Any]:
65
- """Double-click on an element."""
66
- group_id = generate_group_id("browser_double_click", selector[:100])
67
- emit_info(
68
- f"[bold white on blue] BROWSER DOUBLE CLICK [/bold white on blue] 🖱️🖱️ selector='{selector}'",
69
- message_group=group_id,
70
- )
71
- try:
72
- browser_manager = get_camoufox_manager()
73
- page = await browser_manager.get_current_page()
74
-
75
- if not page:
76
- return {"success": False, "error": "No active browser page available"}
77
-
78
- element = page.locator(selector)
79
- await element.wait_for(state="visible", timeout=timeout)
80
- await element.dblclick(force=force, timeout=timeout)
81
-
82
- emit_info(
83
- f"[green]Double-clicked element: {selector}[/green]", message_group=group_id
84
- )
85
-
86
- return {"success": True, "selector": selector, "action": "double_click"}
87
-
88
- except Exception as e:
89
- return {"success": False, "error": str(e), "selector": selector}
90
-
91
-
92
- async def hover_element(
93
- selector: str,
94
- timeout: int = 10000,
95
- force: bool = False,
96
- ) -> Dict[str, Any]:
97
- """Hover over an element."""
98
- group_id = generate_group_id("browser_hover", selector[:100])
99
- emit_info(
100
- f"[bold white on blue] BROWSER HOVER [/bold white on blue] 👆 selector='{selector}'",
101
- message_group=group_id,
102
- )
103
- try:
104
- browser_manager = get_camoufox_manager()
105
- page = await browser_manager.get_current_page()
106
-
107
- if not page:
108
- return {"success": False, "error": "No active browser page available"}
109
-
110
- element = page.locator(selector)
111
- await element.wait_for(state="visible", timeout=timeout)
112
- await element.hover(force=force, timeout=timeout)
113
-
114
- emit_info(
115
- f"[green]Hovered over element: {selector}[/green]", message_group=group_id
116
- )
117
-
118
- return {"success": True, "selector": selector, "action": "hover"}
119
-
120
- except Exception as e:
121
- return {"success": False, "error": str(e), "selector": selector}
122
-
123
-
124
- async def set_element_text(
125
- selector: str,
126
- text: str,
127
- clear_first: bool = True,
128
- timeout: int = 10000,
129
- ) -> Dict[str, Any]:
130
- """Set text in an input element."""
131
- group_id = generate_group_id("browser_set_text", f"{selector[:50]}_{text[:30]}")
132
- emit_info(
133
- f"[bold white on blue] BROWSER SET TEXT [/bold white on blue] ✏️ selector='{selector}' text='{text[:50]}{'...' if len(text) > 50 else ''}'",
134
- message_group=group_id,
135
- )
136
- try:
137
- browser_manager = get_camoufox_manager()
138
- page = await browser_manager.get_current_page()
139
-
140
- if not page:
141
- return {"success": False, "error": "No active browser page available"}
142
-
143
- element = page.locator(selector)
144
- await element.wait_for(state="visible", timeout=timeout)
145
-
146
- if clear_first:
147
- await element.clear(timeout=timeout)
148
-
149
- await element.fill(text, timeout=timeout)
150
-
151
- emit_info(
152
- f"[green]Set text in element: {selector}[/green]", message_group=group_id
153
- )
154
-
155
- return {
156
- "success": True,
157
- "selector": selector,
158
- "text": text,
159
- "action": "set_text",
160
- }
161
-
162
- except Exception as e:
163
- emit_info(f"[red]Set text failed: {str(e)}[/red]", message_group=group_id)
164
- return {"success": False, "error": str(e), "selector": selector, "text": text}
165
-
166
-
167
- async def get_element_text(
168
- selector: str,
169
- timeout: int = 10000,
170
- ) -> Dict[str, Any]:
171
- """Get text content from an element."""
172
- group_id = generate_group_id("browser_get_text", selector[:100])
173
- emit_info(
174
- f"[bold white on blue] BROWSER GET TEXT [/bold white on blue] 📝 selector='{selector}'",
175
- message_group=group_id,
176
- )
177
- try:
178
- browser_manager = get_camoufox_manager()
179
- page = await browser_manager.get_current_page()
180
-
181
- if not page:
182
- return {"success": False, "error": "No active browser page available"}
183
-
184
- element = page.locator(selector)
185
- await element.wait_for(state="visible", timeout=timeout)
186
-
187
- text = await element.text_content()
188
-
189
- return {"success": True, "selector": selector, "text": text}
190
-
191
- except Exception as e:
192
- return {"success": False, "error": str(e), "selector": selector}
193
-
194
-
195
- async def get_element_value(
196
- selector: str,
197
- timeout: int = 10000,
198
- ) -> Dict[str, Any]:
199
- """Get value from an input element."""
200
- group_id = generate_group_id("browser_get_value", selector[:100])
201
- emit_info(
202
- f"[bold white on blue] BROWSER GET VALUE [/bold white on blue] 📎 selector='{selector}'",
203
- message_group=group_id,
204
- )
205
- try:
206
- browser_manager = get_camoufox_manager()
207
- page = await browser_manager.get_current_page()
208
-
209
- if not page:
210
- return {"success": False, "error": "No active browser page available"}
211
-
212
- element = page.locator(selector)
213
- await element.wait_for(state="visible", timeout=timeout)
214
-
215
- value = await element.input_value()
216
-
217
- return {"success": True, "selector": selector, "value": value}
218
-
219
- except Exception as e:
220
- return {"success": False, "error": str(e), "selector": selector}
221
-
222
-
223
- async def select_option(
224
- selector: str,
225
- value: Optional[str] = None,
226
- label: Optional[str] = None,
227
- index: Optional[int] = None,
228
- timeout: int = 10000,
229
- ) -> Dict[str, Any]:
230
- """Select an option in a dropdown/select element."""
231
- option_desc = value or label or str(index) if index is not None else "unknown"
232
- group_id = generate_group_id(
233
- "browser_select_option", f"{selector[:50]}_{option_desc}"
234
- )
235
- emit_info(
236
- f"[bold white on blue] BROWSER SELECT OPTION [/bold white on blue] 📄 selector='{selector}' option='{option_desc}'",
237
- message_group=group_id,
238
- )
239
- try:
240
- browser_manager = get_camoufox_manager()
241
- page = await browser_manager.get_current_page()
242
-
243
- if not page:
244
- return {"success": False, "error": "No active browser page available"}
245
-
246
- element = page.locator(selector)
247
- await element.wait_for(state="visible", timeout=timeout)
248
-
249
- if value is not None:
250
- await element.select_option(value=value, timeout=timeout)
251
- selection = value
252
- elif label is not None:
253
- await element.select_option(label=label, timeout=timeout)
254
- selection = label
255
- elif index is not None:
256
- await element.select_option(index=index, timeout=timeout)
257
- selection = str(index)
258
- else:
259
- return {
260
- "success": False,
261
- "error": "Must specify value, label, or index",
262
- "selector": selector,
263
- }
264
-
265
- emit_info(
266
- f"[green]Selected option in {selector}: {selection}[/green]",
267
- message_group=group_id,
268
- )
269
-
270
- return {"success": True, "selector": selector, "selection": selection}
271
-
272
- except Exception as e:
273
- return {"success": False, "error": str(e), "selector": selector}
274
-
275
-
276
- async def check_element(
277
- selector: str,
278
- timeout: int = 10000,
279
- ) -> Dict[str, Any]:
280
- """Check a checkbox or radio button."""
281
- group_id = generate_group_id("browser_check", selector[:100])
282
- emit_info(
283
- f"[bold white on blue] BROWSER CHECK [/bold white on blue] ☑️ selector='{selector}'",
284
- message_group=group_id,
285
- )
286
- try:
287
- browser_manager = get_camoufox_manager()
288
- page = await browser_manager.get_current_page()
289
-
290
- if not page:
291
- return {"success": False, "error": "No active browser page available"}
292
-
293
- element = page.locator(selector)
294
- await element.wait_for(state="visible", timeout=timeout)
295
- await element.check(timeout=timeout)
296
-
297
- emit_info(f"[green]Checked element: {selector}[/green]", message_group=group_id)
298
-
299
- return {"success": True, "selector": selector, "action": "check"}
300
-
301
- except Exception as e:
302
- return {"success": False, "error": str(e), "selector": selector}
303
-
304
-
305
- async def uncheck_element(
306
- selector: str,
307
- timeout: int = 10000,
308
- ) -> Dict[str, Any]:
309
- """Uncheck a checkbox."""
310
- group_id = generate_group_id("browser_uncheck", selector[:100])
311
- emit_info(
312
- f"[bold white on blue] BROWSER UNCHECK [/bold white on blue] ☐️ selector='{selector}'",
313
- message_group=group_id,
314
- )
315
- try:
316
- browser_manager = get_camoufox_manager()
317
- page = await browser_manager.get_current_page()
318
-
319
- if not page:
320
- return {"success": False, "error": "No active browser page available"}
321
-
322
- element = page.locator(selector)
323
- await element.wait_for(state="visible", timeout=timeout)
324
- await element.uncheck(timeout=timeout)
325
-
326
- emit_info(
327
- f"[green]Unchecked element: {selector}[/green]", message_group=group_id
328
- )
329
-
330
- return {"success": True, "selector": selector, "action": "uncheck"}
331
-
332
- except Exception as e:
333
- return {"success": False, "error": str(e), "selector": selector}
334
-
335
-
336
- # Tool registration functions
337
- def register_click_element(agent):
338
- """Register the click element tool."""
339
-
340
- @agent.tool
341
- async def browser_click(
342
- context: RunContext,
343
- selector: str,
344
- timeout: int = 10000,
345
- force: bool = False,
346
- button: str = "left",
347
- modifiers: Optional[List[str]] = None,
348
- ) -> Dict[str, Any]:
349
- """
350
- Click on an element in the browser.
351
-
352
- Args:
353
- selector: CSS or XPath selector for the element
354
- timeout: Timeout in milliseconds to wait for element
355
- force: Skip actionability checks and force the click
356
- button: Mouse button to click (left, right, middle)
357
- modifiers: Modifier keys to hold (Alt, Control, Meta, Shift)
358
-
359
- Returns:
360
- Dict with click results
361
- """
362
- return await click_element(selector, timeout, force, button, modifiers)
363
-
364
-
365
- def register_double_click_element(agent):
366
- """Register the double-click element tool."""
367
-
368
- @agent.tool
369
- async def browser_double_click(
370
- context: RunContext,
371
- selector: str,
372
- timeout: int = 10000,
373
- force: bool = False,
374
- ) -> Dict[str, Any]:
375
- """
376
- Double-click on an element in the browser.
377
-
378
- Args:
379
- selector: CSS or XPath selector for the element
380
- timeout: Timeout in milliseconds to wait for element
381
- force: Skip actionability checks and force the double-click
382
-
383
- Returns:
384
- Dict with double-click results
385
- """
386
- return await double_click_element(selector, timeout, force)
387
-
388
-
389
- def register_hover_element(agent):
390
- """Register the hover element tool."""
391
-
392
- @agent.tool
393
- async def browser_hover(
394
- context: RunContext,
395
- selector: str,
396
- timeout: int = 10000,
397
- force: bool = False,
398
- ) -> Dict[str, Any]:
399
- """
400
- Hover over an element in the browser.
401
-
402
- Args:
403
- selector: CSS or XPath selector for the element
404
- timeout: Timeout in milliseconds to wait for element
405
- force: Skip actionability checks and force the hover
406
-
407
- Returns:
408
- Dict with hover results
409
- """
410
- return await hover_element(selector, timeout, force)
411
-
412
-
413
- def register_set_element_text(agent):
414
- """Register the set element text tool."""
415
-
416
- @agent.tool
417
- async def browser_set_text(
418
- context: RunContext,
419
- selector: str,
420
- text: str,
421
- clear_first: bool = True,
422
- timeout: int = 10000,
423
- ) -> Dict[str, Any]:
424
- """
425
- Set text in an input element.
426
-
427
- Args:
428
- selector: CSS or XPath selector for the input element
429
- text: Text to enter
430
- clear_first: Whether to clear existing text first
431
- timeout: Timeout in milliseconds to wait for element
432
-
433
- Returns:
434
- Dict with text input results
435
- """
436
- return await set_element_text(selector, text, clear_first, timeout)
437
-
438
-
439
- def register_get_element_text(agent):
440
- """Register the get element text tool."""
441
-
442
- @agent.tool
443
- async def browser_get_text(
444
- context: RunContext,
445
- selector: str,
446
- timeout: int = 10000,
447
- ) -> Dict[str, Any]:
448
- """
449
- Get text content from an element.
450
-
451
- Args:
452
- selector: CSS or XPath selector for the element
453
- timeout: Timeout in milliseconds to wait for element
454
-
455
- Returns:
456
- Dict with element text content
457
- """
458
- return await get_element_text(selector, timeout)
459
-
460
-
461
- def register_get_element_value(agent):
462
- """Register the get element value tool."""
463
-
464
- @agent.tool
465
- async def browser_get_value(
466
- context: RunContext,
467
- selector: str,
468
- timeout: int = 10000,
469
- ) -> Dict[str, Any]:
470
- """
471
- Get value from an input element.
472
-
473
- Args:
474
- selector: CSS or XPath selector for the input element
475
- timeout: Timeout in milliseconds to wait for element
476
-
477
- Returns:
478
- Dict with element value
479
- """
480
- return await get_element_value(selector, timeout)
481
-
482
-
483
- def register_select_option(agent):
484
- """Register the select option tool."""
485
-
486
- @agent.tool
487
- async def browser_select_option(
488
- context: RunContext,
489
- selector: str,
490
- value: Optional[str] = None,
491
- label: Optional[str] = None,
492
- index: Optional[int] = None,
493
- timeout: int = 10000,
494
- ) -> Dict[str, Any]:
495
- """
496
- Select an option in a dropdown/select element.
497
-
498
- Args:
499
- selector: CSS or XPath selector for the select element
500
- value: Option value to select
501
- label: Option label text to select
502
- index: Option index to select (0-based)
503
- timeout: Timeout in milliseconds to wait for element
504
-
505
- Returns:
506
- Dict with selection results
507
- """
508
- return await select_option(selector, value, label, index, timeout)
509
-
510
-
511
- def register_browser_check(agent):
512
- """Register checkbox/radio button check tool."""
513
-
514
- @agent.tool
515
- async def browser_check(
516
- context: RunContext,
517
- selector: str,
518
- timeout: int = 10000,
519
- ) -> Dict[str, Any]:
520
- """
521
- Check a checkbox or radio button.
522
-
523
- Args:
524
- selector: CSS or XPath selector for the checkbox/radio
525
- timeout: Timeout in milliseconds to wait for element
526
-
527
- Returns:
528
- Dict with check results
529
- """
530
- return await check_element(selector, timeout)
531
-
532
-
533
- def register_browser_uncheck(agent):
534
- """Register checkbox uncheck tool."""
535
-
536
- @agent.tool
537
- async def browser_uncheck(
538
- context: RunContext,
539
- selector: str,
540
- timeout: int = 10000,
541
- ) -> Dict[str, Any]:
542
- """
543
- Uncheck a checkbox.
544
-
545
- Args:
546
- selector: CSS or XPath selector for the checkbox
547
- timeout: Timeout in milliseconds to wait for element
548
-
549
- Returns:
550
- Dict with uncheck results
551
- """
552
- return await uncheck_element(selector, timeout)