code-puppy 0.0.170__py3-none-any.whl → 0.0.172__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 (66) hide show
  1. code_puppy/agent.py +10 -2
  2. code_puppy/agents/agent_creator_agent.py +0 -3
  3. code_puppy/agents/agent_qa_kitten.py +203 -0
  4. code_puppy/agents/base_agent.py +9 -0
  5. code_puppy/command_line/command_handler.py +68 -28
  6. code_puppy/command_line/mcp/add_command.py +1 -1
  7. code_puppy/command_line/mcp/base.py +1 -1
  8. code_puppy/command_line/mcp/install_command.py +1 -1
  9. code_puppy/command_line/mcp/list_command.py +1 -1
  10. code_puppy/command_line/mcp/search_command.py +1 -1
  11. code_puppy/command_line/mcp/start_all_command.py +1 -1
  12. code_puppy/command_line/mcp/status_command.py +2 -2
  13. code_puppy/command_line/mcp/stop_all_command.py +1 -1
  14. code_puppy/command_line/mcp/utils.py +1 -1
  15. code_puppy/command_line/mcp/wizard_utils.py +2 -2
  16. code_puppy/config.py +142 -12
  17. code_puppy/http_utils.py +50 -24
  18. code_puppy/{mcp → mcp_}/config_wizard.py +1 -1
  19. code_puppy/{mcp → mcp_}/examples/retry_example.py +1 -1
  20. code_puppy/{mcp → mcp_}/managed_server.py +1 -1
  21. code_puppy/{mcp → mcp_}/server_registry_catalog.py +1 -3
  22. code_puppy/message_history_processor.py +121 -125
  23. code_puppy/state_management.py +86 -127
  24. code_puppy/tools/__init__.py +103 -6
  25. code_puppy/tools/browser/__init__.py +0 -0
  26. code_puppy/tools/browser/browser_control.py +293 -0
  27. code_puppy/tools/browser/browser_interactions.py +552 -0
  28. code_puppy/tools/browser/browser_locators.py +642 -0
  29. code_puppy/tools/browser/browser_navigation.py +251 -0
  30. code_puppy/tools/browser/browser_screenshot.py +242 -0
  31. code_puppy/tools/browser/browser_scripts.py +478 -0
  32. code_puppy/tools/browser/browser_workflows.py +196 -0
  33. code_puppy/tools/browser/camoufox_manager.py +194 -0
  34. code_puppy/tools/browser/vqa_agent.py +66 -0
  35. code_puppy/tools/browser_control.py +293 -0
  36. code_puppy/tools/browser_interactions.py +552 -0
  37. code_puppy/tools/browser_locators.py +642 -0
  38. code_puppy/tools/browser_navigation.py +251 -0
  39. code_puppy/tools/browser_screenshot.py +278 -0
  40. code_puppy/tools/browser_scripts.py +478 -0
  41. code_puppy/tools/browser_workflows.py +215 -0
  42. code_puppy/tools/camoufox_manager.py +150 -0
  43. code_puppy/tools/command_runner.py +12 -7
  44. code_puppy/tools/file_operations.py +7 -7
  45. code_puppy/tui/app.py +4 -2
  46. code_puppy/tui/components/custom_widgets.py +1 -1
  47. code_puppy/tui/screens/mcp_install_wizard.py +8 -8
  48. {code_puppy-0.0.170.dist-info → code_puppy-0.0.172.dist-info}/METADATA +4 -2
  49. {code_puppy-0.0.170.dist-info → code_puppy-0.0.172.dist-info}/RECORD +66 -47
  50. /code_puppy/{mcp → mcp_}/__init__.py +0 -0
  51. /code_puppy/{mcp → mcp_}/async_lifecycle.py +0 -0
  52. /code_puppy/{mcp → mcp_}/blocking_startup.py +0 -0
  53. /code_puppy/{mcp → mcp_}/captured_stdio_server.py +0 -0
  54. /code_puppy/{mcp → mcp_}/circuit_breaker.py +0 -0
  55. /code_puppy/{mcp → mcp_}/dashboard.py +0 -0
  56. /code_puppy/{mcp → mcp_}/error_isolation.py +0 -0
  57. /code_puppy/{mcp → mcp_}/health_monitor.py +0 -0
  58. /code_puppy/{mcp → mcp_}/manager.py +0 -0
  59. /code_puppy/{mcp → mcp_}/registry.py +0 -0
  60. /code_puppy/{mcp → mcp_}/retry_manager.py +0 -0
  61. /code_puppy/{mcp → mcp_}/status_tracker.py +0 -0
  62. /code_puppy/{mcp → mcp_}/system_tools.py +0 -0
  63. {code_puppy-0.0.170.data → code_puppy-0.0.172.data}/data/code_puppy/models.json +0 -0
  64. {code_puppy-0.0.170.dist-info → code_puppy-0.0.172.dist-info}/WHEEL +0 -0
  65. {code_puppy-0.0.170.dist-info → code_puppy-0.0.172.dist-info}/entry_points.txt +0 -0
  66. {code_puppy-0.0.170.dist-info → code_puppy-0.0.172.dist-info}/licenses/LICENSE +0 -0
@@ -1,20 +1,71 @@
1
1
  from code_puppy.messaging import emit_warning
2
- from code_puppy.tools.agent_tools import (
3
- register_list_agents,
4
- register_invoke_agent,
2
+ from code_puppy.tools.agent_tools import register_invoke_agent, register_list_agents
3
+
4
+ # Browser automation tools
5
+ from code_puppy.tools.browser.browser_control import (
6
+ register_close_browser,
7
+ register_create_new_page,
8
+ register_get_browser_status,
9
+ register_initialize_browser,
10
+ register_list_pages,
11
+ )
12
+ from code_puppy.tools.browser.browser_interactions import (
13
+ register_browser_check,
14
+ register_browser_uncheck,
15
+ register_click_element,
16
+ register_double_click_element,
17
+ register_get_element_text,
18
+ register_get_element_value,
19
+ register_hover_element,
20
+ register_select_option,
21
+ register_set_element_text,
22
+ )
23
+ from code_puppy.tools.browser.browser_locators import (
24
+ register_find_buttons,
25
+ register_find_by_label,
26
+ register_find_by_placeholder,
27
+ register_find_by_role,
28
+ register_find_by_test_id,
29
+ register_find_by_text,
30
+ register_find_links,
31
+ register_run_xpath_query,
32
+ )
33
+ from code_puppy.tools.browser.browser_navigation import (
34
+ register_browser_go_back,
35
+ register_browser_go_forward,
36
+ register_get_page_info,
37
+ register_navigate_to_url,
38
+ register_reload_page,
39
+ register_wait_for_load_state,
40
+ )
41
+ from code_puppy.tools.browser.browser_screenshot import (
42
+ register_take_screenshot_and_analyze,
43
+ )
44
+ from code_puppy.tools.browser.browser_scripts import (
45
+ register_browser_clear_highlights,
46
+ register_browser_highlight_element,
47
+ register_execute_javascript,
48
+ register_scroll_page,
49
+ register_scroll_to_element,
50
+ register_set_viewport_size,
51
+ register_wait_for_element,
52
+ )
53
+ from code_puppy.tools.browser.browser_workflows import (
54
+ register_list_workflows,
55
+ register_read_workflow,
56
+ register_save_workflow,
5
57
  )
6
58
  from code_puppy.tools.command_runner import (
7
59
  register_agent_run_shell_command,
8
60
  register_agent_share_your_reasoning,
9
61
  )
10
- from code_puppy.tools.file_modifications import register_edit_file, register_delete_file
62
+ from code_puppy.tools.file_modifications import register_delete_file, register_edit_file
11
63
  from code_puppy.tools.file_operations import (
64
+ register_grep,
12
65
  register_list_files,
13
66
  register_read_file,
14
- register_grep,
15
67
  )
16
68
 
17
-
18
69
  # Map of tool names to their individual registration functions
19
70
  TOOL_REGISTRY = {
20
71
  # Agent Tools
@@ -30,6 +81,52 @@ TOOL_REGISTRY = {
30
81
  # Command Runner
31
82
  "agent_run_shell_command": register_agent_run_shell_command,
32
83
  "agent_share_your_reasoning": register_agent_share_your_reasoning,
84
+ # Browser Control
85
+ "browser_initialize": register_initialize_browser,
86
+ "browser_close": register_close_browser,
87
+ "browser_status": register_get_browser_status,
88
+ "browser_new_page": register_create_new_page,
89
+ "browser_list_pages": register_list_pages,
90
+ # Browser Navigation
91
+ "browser_navigate": register_navigate_to_url,
92
+ "browser_get_page_info": register_get_page_info,
93
+ "browser_go_back": register_browser_go_back,
94
+ "browser_go_forward": register_browser_go_forward,
95
+ "browser_reload": register_reload_page,
96
+ "browser_wait_for_load": register_wait_for_load_state,
97
+ # Browser Element Discovery
98
+ "browser_find_by_role": register_find_by_role,
99
+ "browser_find_by_text": register_find_by_text,
100
+ "browser_find_by_label": register_find_by_label,
101
+ "browser_find_by_placeholder": register_find_by_placeholder,
102
+ "browser_find_by_test_id": register_find_by_test_id,
103
+ "browser_xpath_query": register_run_xpath_query,
104
+ "browser_find_buttons": register_find_buttons,
105
+ "browser_find_links": register_find_links,
106
+ # Browser Element Interactions
107
+ "browser_click": register_click_element,
108
+ "browser_double_click": register_double_click_element,
109
+ "browser_hover": register_hover_element,
110
+ "browser_set_text": register_set_element_text,
111
+ "browser_get_text": register_get_element_text,
112
+ "browser_get_value": register_get_element_value,
113
+ "browser_select_option": register_select_option,
114
+ "browser_check": register_browser_check,
115
+ "browser_uncheck": register_browser_uncheck,
116
+ # Browser Scripts and Advanced Features
117
+ "browser_execute_js": register_execute_javascript,
118
+ "browser_scroll": register_scroll_page,
119
+ "browser_scroll_to_element": register_scroll_to_element,
120
+ "browser_set_viewport": register_set_viewport_size,
121
+ "browser_wait_for_element": register_wait_for_element,
122
+ "browser_highlight_element": register_browser_highlight_element,
123
+ "browser_clear_highlights": register_browser_clear_highlights,
124
+ # Browser Screenshots and VQA
125
+ "browser_screenshot_analyze": register_take_screenshot_and_analyze,
126
+ # Browser Workflows
127
+ "browser_save_workflow": register_save_workflow,
128
+ "browser_list_workflows": register_list_workflows,
129
+ "browser_read_workflow": register_read_workflow,
33
130
  }
34
131
 
35
132
 
File without changes
@@ -0,0 +1,293 @@
1
+ """Browser initialization and control tools."""
2
+
3
+ from typing import Any, Dict, 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 initialize_browser(
14
+ headless: bool = False,
15
+ browser_type: str = "chromium",
16
+ homepage: str = "https://www.google.com",
17
+ ) -> Dict[str, Any]:
18
+ """Initialize the browser with specified settings."""
19
+ group_id = generate_group_id("browser_initialize", f"{browser_type}_{homepage}")
20
+ emit_info(
21
+ f"[bold white on blue] BROWSER INITIALIZE [/bold white on blue] 🌐 {browser_type} → {homepage}",
22
+ message_group=group_id,
23
+ )
24
+ try:
25
+ browser_manager = get_camoufox_manager()
26
+
27
+ # Configure browser settings
28
+ browser_manager.headless = headless
29
+ browser_manager.browser_type = browser_type
30
+ browser_manager.homepage = homepage
31
+
32
+ # Initialize browser
33
+ await browser_manager.async_initialize()
34
+
35
+ # Get page info
36
+ page = await browser_manager.get_current_page()
37
+ if page:
38
+ url = page.url
39
+ title = await page.title()
40
+ else:
41
+ url = "Unknown"
42
+ title = "Unknown"
43
+
44
+ emit_info(
45
+ "[green]Browser initialized successfully[/green]", message_group=group_id
46
+ )
47
+
48
+ return {
49
+ "success": True,
50
+ "browser_type": browser_type,
51
+ "headless": headless,
52
+ "homepage": homepage,
53
+ "current_url": url,
54
+ "current_title": title,
55
+ }
56
+
57
+ except Exception as e:
58
+ emit_info(
59
+ f"[red]Browser initialization failed: {str(e)}[/red]",
60
+ message_group=group_id,
61
+ )
62
+ return {
63
+ "success": False,
64
+ "error": str(e),
65
+ "browser_type": browser_type,
66
+ "headless": headless,
67
+ }
68
+
69
+
70
+ async def close_browser() -> Dict[str, Any]:
71
+ """Close the browser and clean up resources."""
72
+ group_id = generate_group_id("browser_close")
73
+ emit_info(
74
+ "[bold white on blue] BROWSER CLOSE [/bold white on blue] 🔒",
75
+ message_group=group_id,
76
+ )
77
+ try:
78
+ browser_manager = get_camoufox_manager()
79
+ await browser_manager.close()
80
+
81
+ emit_info(
82
+ "[yellow]Browser closed successfully[/yellow]", message_group=group_id
83
+ )
84
+
85
+ return {"success": True, "message": "Browser closed"}
86
+
87
+ except Exception as e:
88
+ return {"success": False, "error": str(e)}
89
+
90
+
91
+ async def get_browser_status() -> Dict[str, Any]:
92
+ """Get current browser status and information."""
93
+ group_id = generate_group_id("browser_status")
94
+ emit_info(
95
+ "[bold white on blue] BROWSER STATUS [/bold white on blue] 📊",
96
+ message_group=group_id,
97
+ )
98
+ try:
99
+ browser_manager = get_camoufox_manager()
100
+
101
+ if not browser_manager._initialized:
102
+ return {
103
+ "success": True,
104
+ "status": "not_initialized",
105
+ "browser_type": browser_manager.browser_type,
106
+ "headless": browser_manager.headless,
107
+ }
108
+
109
+ page = await browser_manager.get_current_page()
110
+ if page:
111
+ url = page.url
112
+ title = await page.title()
113
+
114
+ # Get all pages
115
+ all_pages = await browser_manager.get_all_pages()
116
+ page_count = len(all_pages)
117
+ else:
118
+ url = None
119
+ title = None
120
+ page_count = 0
121
+
122
+ return {
123
+ "success": True,
124
+ "status": "initialized",
125
+ "browser_type": browser_manager.browser_type,
126
+ "headless": browser_manager.headless,
127
+ "current_url": url,
128
+ "current_title": title,
129
+ "page_count": page_count,
130
+ }
131
+
132
+ except Exception as e:
133
+ return {"success": False, "error": str(e)}
134
+
135
+
136
+ async def create_new_page(url: Optional[str] = None) -> Dict[str, Any]:
137
+ """Create a new browser page/tab."""
138
+ group_id = generate_group_id("browser_new_page", url or "blank")
139
+ emit_info(
140
+ f"[bold white on blue] BROWSER NEW PAGE [/bold white on blue] 📄 {url or 'blank page'}",
141
+ message_group=group_id,
142
+ )
143
+ try:
144
+ browser_manager = get_camoufox_manager()
145
+
146
+ if not browser_manager._initialized:
147
+ return {
148
+ "success": False,
149
+ "error": "Browser not initialized. Use browser_initialize first.",
150
+ }
151
+
152
+ page = await browser_manager.new_page(url)
153
+
154
+ final_url = page.url
155
+ title = await page.title()
156
+
157
+ emit_info(
158
+ f"[green]Created new page: {final_url}[/green]", message_group=group_id
159
+ )
160
+
161
+ return {"success": True, "url": final_url, "title": title, "requested_url": url}
162
+
163
+ except Exception as e:
164
+ return {"success": False, "error": str(e), "url": url}
165
+
166
+
167
+ async def list_pages() -> Dict[str, Any]:
168
+ """List all open browser pages/tabs."""
169
+ group_id = generate_group_id("browser_list_pages")
170
+ emit_info(
171
+ "[bold white on blue] BROWSER LIST PAGES [/bold white on blue] 📋",
172
+ message_group=group_id,
173
+ )
174
+ try:
175
+ browser_manager = get_camoufox_manager()
176
+
177
+ if not browser_manager._initialized:
178
+ return {"success": False, "error": "Browser not initialized"}
179
+
180
+ all_pages = await browser_manager.get_all_pages()
181
+
182
+ pages_info = []
183
+ for i, page in enumerate(all_pages):
184
+ try:
185
+ url = page.url
186
+ title = await page.title()
187
+ is_closed = page.is_closed()
188
+
189
+ pages_info.append(
190
+ {"index": i, "url": url, "title": title, "closed": is_closed}
191
+ )
192
+ except Exception as e:
193
+ pages_info.append(
194
+ {
195
+ "index": i,
196
+ "url": "Error",
197
+ "title": "Error",
198
+ "error": str(e),
199
+ "closed": True,
200
+ }
201
+ )
202
+
203
+ return {"success": True, "page_count": len(all_pages), "pages": pages_info}
204
+
205
+ except Exception as e:
206
+ return {"success": False, "error": str(e)}
207
+
208
+
209
+ # Tool registration functions
210
+ def register_initialize_browser(agent):
211
+ """Register the browser initialization tool."""
212
+
213
+ @agent.tool
214
+ async def browser_initialize(
215
+ context: RunContext,
216
+ headless: bool = False,
217
+ browser_type: str = "chromium",
218
+ homepage: str = "https://www.google.com",
219
+ ) -> Dict[str, Any]:
220
+ """
221
+ Initialize the browser with specified settings. Must be called before using other browser tools.
222
+
223
+ Args:
224
+ headless: Run browser in headless mode (no GUI)
225
+ browser_type: Browser engine (chromium, firefox, webkit)
226
+ homepage: Initial page to load
227
+
228
+ Returns:
229
+ Dict with initialization results
230
+ """
231
+ return await initialize_browser(headless, browser_type, homepage)
232
+
233
+
234
+ def register_close_browser(agent):
235
+ """Register the browser close tool."""
236
+
237
+ @agent.tool
238
+ async def browser_close(context: RunContext) -> Dict[str, Any]:
239
+ """
240
+ Close the browser and clean up all resources.
241
+
242
+ Returns:
243
+ Dict with close results
244
+ """
245
+ return await close_browser()
246
+
247
+
248
+ def register_get_browser_status(agent):
249
+ """Register the browser status tool."""
250
+
251
+ @agent.tool
252
+ async def browser_status(context: RunContext) -> Dict[str, Any]:
253
+ """
254
+ Get current browser status and information.
255
+
256
+ Returns:
257
+ Dict with browser status and metadata
258
+ """
259
+ return await get_browser_status()
260
+
261
+
262
+ def register_create_new_page(agent):
263
+ """Register the new page creation tool."""
264
+
265
+ @agent.tool
266
+ async def browser_new_page(
267
+ context: RunContext,
268
+ url: Optional[str] = None,
269
+ ) -> Dict[str, Any]:
270
+ """
271
+ Create a new browser page/tab.
272
+
273
+ Args:
274
+ url: Optional URL to navigate to in the new page
275
+
276
+ Returns:
277
+ Dict with new page results
278
+ """
279
+ return await create_new_page(url)
280
+
281
+
282
+ def register_list_pages(agent):
283
+ """Register the list pages tool."""
284
+
285
+ @agent.tool
286
+ async def browser_list_pages(context: RunContext) -> Dict[str, Any]:
287
+ """
288
+ List all open browser pages/tabs.
289
+
290
+ Returns:
291
+ Dict with information about all open pages
292
+ """
293
+ return await list_pages()