code-puppy 0.0.171__tar.gz → 0.0.172__tar.gz
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.
- {code_puppy-0.0.171 → code_puppy-0.0.172}/PKG-INFO +3 -1
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/agent.py +3 -3
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/agents/agent_creator_agent.py +0 -3
- code_puppy-0.0.172/code_puppy/agents/agent_qa_kitten.py +203 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/agents/base_agent.py +9 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/command_line/command_handler.py +68 -28
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/command_line/mcp/add_command.py +1 -1
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/command_line/mcp/base.py +1 -1
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/command_line/mcp/install_command.py +1 -1
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/command_line/mcp/list_command.py +1 -1
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/command_line/mcp/search_command.py +1 -1
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/command_line/mcp/start_all_command.py +1 -1
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/command_line/mcp/status_command.py +2 -2
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/command_line/mcp/stop_all_command.py +1 -1
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/command_line/mcp/utils.py +1 -1
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/command_line/mcp/wizard_utils.py +2 -2
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/config.py +142 -12
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/http_utils.py +50 -24
- {code_puppy-0.0.171/code_puppy/mcp → code_puppy-0.0.172/code_puppy/mcp_}/config_wizard.py +1 -1
- {code_puppy-0.0.171/code_puppy/mcp → code_puppy-0.0.172/code_puppy/mcp_}/examples/retry_example.py +1 -1
- {code_puppy-0.0.171/code_puppy/mcp → code_puppy-0.0.172/code_puppy/mcp_}/managed_server.py +1 -1
- {code_puppy-0.0.171/code_puppy/mcp → code_puppy-0.0.172/code_puppy/mcp_}/server_registry_catalog.py +1 -3
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/message_history_processor.py +1 -61
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/state_management.py +4 -2
- code_puppy-0.0.172/code_puppy/tools/__init__.py +167 -0
- code_puppy-0.0.172/code_puppy/tools/browser/__init__.py +0 -0
- code_puppy-0.0.172/code_puppy/tools/browser/browser_control.py +293 -0
- code_puppy-0.0.172/code_puppy/tools/browser/browser_interactions.py +552 -0
- code_puppy-0.0.172/code_puppy/tools/browser/browser_locators.py +642 -0
- code_puppy-0.0.172/code_puppy/tools/browser/browser_navigation.py +251 -0
- code_puppy-0.0.172/code_puppy/tools/browser/browser_screenshot.py +242 -0
- code_puppy-0.0.172/code_puppy/tools/browser/browser_scripts.py +478 -0
- code_puppy-0.0.172/code_puppy/tools/browser/browser_workflows.py +196 -0
- code_puppy-0.0.172/code_puppy/tools/browser/camoufox_manager.py +194 -0
- code_puppy-0.0.172/code_puppy/tools/browser/vqa_agent.py +66 -0
- code_puppy-0.0.172/code_puppy/tools/browser_control.py +293 -0
- code_puppy-0.0.172/code_puppy/tools/browser_interactions.py +552 -0
- code_puppy-0.0.172/code_puppy/tools/browser_locators.py +642 -0
- code_puppy-0.0.172/code_puppy/tools/browser_navigation.py +251 -0
- code_puppy-0.0.172/code_puppy/tools/browser_screenshot.py +278 -0
- code_puppy-0.0.172/code_puppy/tools/browser_scripts.py +478 -0
- code_puppy-0.0.172/code_puppy/tools/browser_workflows.py +215 -0
- code_puppy-0.0.172/code_puppy/tools/camoufox_manager.py +150 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/tools/command_runner.py +12 -7
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/tools/file_operations.py +7 -7
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/tui/components/custom_widgets.py +1 -1
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/tui/screens/mcp_install_wizard.py +8 -8
- {code_puppy-0.0.171 → code_puppy-0.0.172}/pyproject.toml +3 -1
- code_puppy-0.0.171/code_puppy/tools/__init__.py +0 -70
- {code_puppy-0.0.171 → code_puppy-0.0.172}/.gitignore +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/LICENSE +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/README.md +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/__init__.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/__main__.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/agents/__init__.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/agents/agent_code_puppy.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/agents/agent_manager.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/agents/agent_orchestrator.json +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/agents/json_agent.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/agents/runtime_manager.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/callbacks.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/command_line/__init__.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/command_line/file_path_completion.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/command_line/load_context_completion.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/command_line/mcp/__init__.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/command_line/mcp/handler.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/command_line/mcp/help_command.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/command_line/mcp/logs_command.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/command_line/mcp/remove_command.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/command_line/mcp/restart_command.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/command_line/mcp/start_command.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/command_line/mcp/stop_command.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/command_line/mcp/test_command.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/command_line/meta_command_handler.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/command_line/model_picker_completion.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/command_line/motd.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/command_line/prompt_toolkit_completion.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/command_line/utils.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/main.py +0 -0
- {code_puppy-0.0.171/code_puppy/mcp → code_puppy-0.0.172/code_puppy/mcp_}/__init__.py +0 -0
- {code_puppy-0.0.171/code_puppy/mcp → code_puppy-0.0.172/code_puppy/mcp_}/async_lifecycle.py +0 -0
- {code_puppy-0.0.171/code_puppy/mcp → code_puppy-0.0.172/code_puppy/mcp_}/blocking_startup.py +0 -0
- {code_puppy-0.0.171/code_puppy/mcp → code_puppy-0.0.172/code_puppy/mcp_}/captured_stdio_server.py +0 -0
- {code_puppy-0.0.171/code_puppy/mcp → code_puppy-0.0.172/code_puppy/mcp_}/circuit_breaker.py +0 -0
- {code_puppy-0.0.171/code_puppy/mcp → code_puppy-0.0.172/code_puppy/mcp_}/dashboard.py +0 -0
- {code_puppy-0.0.171/code_puppy/mcp → code_puppy-0.0.172/code_puppy/mcp_}/error_isolation.py +0 -0
- {code_puppy-0.0.171/code_puppy/mcp → code_puppy-0.0.172/code_puppy/mcp_}/health_monitor.py +0 -0
- {code_puppy-0.0.171/code_puppy/mcp → code_puppy-0.0.172/code_puppy/mcp_}/manager.py +0 -0
- {code_puppy-0.0.171/code_puppy/mcp → code_puppy-0.0.172/code_puppy/mcp_}/registry.py +0 -0
- {code_puppy-0.0.171/code_puppy/mcp → code_puppy-0.0.172/code_puppy/mcp_}/retry_manager.py +0 -0
- {code_puppy-0.0.171/code_puppy/mcp → code_puppy-0.0.172/code_puppy/mcp_}/status_tracker.py +0 -0
- {code_puppy-0.0.171/code_puppy/mcp → code_puppy-0.0.172/code_puppy/mcp_}/system_tools.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/messaging/__init__.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/messaging/message_queue.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/messaging/queue_console.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/messaging/renderers.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/messaging/spinner/__init__.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/messaging/spinner/console_spinner.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/messaging/spinner/spinner_base.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/messaging/spinner/textual_spinner.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/model_factory.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/models.json +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/plugins/__init__.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/reopenable_async_client.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/round_robin_model.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/status_display.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/summarization_agent.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/tools/agent_tools.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/tools/common.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/tools/file_modifications.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/tools/tools_content.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/tui/__init__.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/tui/app.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/tui/components/__init__.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/tui/components/chat_view.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/tui/components/command_history_modal.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/tui/components/copy_button.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/tui/components/human_input_modal.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/tui/components/input_area.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/tui/components/sidebar.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/tui/components/status_bar.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/tui/messages.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/tui/models/__init__.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/tui/models/chat_message.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/tui/models/command_history.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/tui/models/enums.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/tui/screens/__init__.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/tui/screens/help.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/tui/screens/settings.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/tui/screens/tools.py +0 -0
- {code_puppy-0.0.171 → code_puppy-0.0.172}/code_puppy/version_checker.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: code-puppy
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.172
|
|
4
4
|
Summary: Code generation agent
|
|
5
5
|
Project-URL: repository, https://github.com/mpfaffenberger/code_puppy
|
|
6
6
|
Project-URL: HomePage, https://github.com/mpfaffenberger/code_puppy
|
|
@@ -16,6 +16,7 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
16
16
|
Classifier: Topic :: Software Development :: Code Generators
|
|
17
17
|
Requires-Python: >=3.11
|
|
18
18
|
Requires-Dist: bs4>=0.0.2
|
|
19
|
+
Requires-Dist: camoufox>=0.4.11
|
|
19
20
|
Requires-Dist: fastapi>=0.110.0
|
|
20
21
|
Requires-Dist: httpx-limiter>=0.3.0
|
|
21
22
|
Requires-Dist: httpx>=0.24.1
|
|
@@ -23,6 +24,7 @@ Requires-Dist: json-repair>=0.46.2
|
|
|
23
24
|
Requires-Dist: logfire>=0.7.1
|
|
24
25
|
Requires-Dist: openai>=1.99.1
|
|
25
26
|
Requires-Dist: pathspec>=0.11.0
|
|
27
|
+
Requires-Dist: playwright>=1.40.0
|
|
26
28
|
Requires-Dist: prompt-toolkit>=3.0.38
|
|
27
29
|
Requires-Dist: pydantic-ai>=1.0.10
|
|
28
30
|
Requires-Dist: pydantic>=2.4.0
|
|
@@ -48,7 +48,7 @@ _code_generation_agent = None
|
|
|
48
48
|
def _load_mcp_servers(extra_headers: Optional[Dict[str, str]] = None):
|
|
49
49
|
"""Load MCP servers using the new manager while maintaining backward compatibility."""
|
|
50
50
|
from code_puppy.config import get_value, load_mcp_server_configs
|
|
51
|
-
from code_puppy.
|
|
51
|
+
from code_puppy.mcp_ import ServerConfig, get_mcp_manager
|
|
52
52
|
|
|
53
53
|
# Check if MCP servers are disabled
|
|
54
54
|
mcp_disabled = get_value("disable_mcp_servers")
|
|
@@ -113,7 +113,7 @@ def _load_mcp_servers(extra_headers: Optional[Dict[str, str]] = None):
|
|
|
113
113
|
|
|
114
114
|
def reload_mcp_servers():
|
|
115
115
|
"""Reload MCP servers without restarting the agent."""
|
|
116
|
-
from code_puppy.
|
|
116
|
+
from code_puppy.mcp_ import get_mcp_manager
|
|
117
117
|
|
|
118
118
|
manager = get_mcp_manager()
|
|
119
119
|
# Reload configurations
|
|
@@ -174,7 +174,7 @@ def reload_code_generation_agent(message_group: str | None):
|
|
|
174
174
|
|
|
175
175
|
model_settings = ModelSettings(**model_settings_dict)
|
|
176
176
|
if "gpt-5" in model_name:
|
|
177
|
-
model_settings_dict["openai_reasoning_effort"] = "
|
|
177
|
+
model_settings_dict["openai_reasoning_effort"] = "off"
|
|
178
178
|
model_settings_dict["extra_body"] = {
|
|
179
179
|
"verbosity": "low"
|
|
180
180
|
}
|
|
@@ -245,9 +245,6 @@ Best-practice guidelines for `invoke_agent`:
|
|
|
245
245
|
Your solutions should be production-ready, maintainable, and follow best practices for the chosen language.
|
|
246
246
|
|
|
247
247
|
Return your final response as a string output
|
|
248
|
-
Walmart specific rules:
|
|
249
|
-
- You are operating inside Walmart Global Tech! Yay!
|
|
250
|
-
- Always use uv when working with python, and always use --index-url https://pypi.ci.artifacts.walmart.com/artifactory/api/pypi/external-pypi/simple
|
|
251
248
|
|
|
252
249
|
## Tool Templates:
|
|
253
250
|
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
"""Quality Assurance Kitten - Playwright-powered browser automation agent."""
|
|
2
|
+
|
|
3
|
+
from .base_agent import BaseAgent
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class QualityAssuranceKittenAgent(BaseAgent):
|
|
7
|
+
"""Quality Assurance Kitten - Advanced browser automation with Playwright."""
|
|
8
|
+
|
|
9
|
+
@property
|
|
10
|
+
def name(self) -> str:
|
|
11
|
+
return "qa-kitten"
|
|
12
|
+
|
|
13
|
+
@property
|
|
14
|
+
def display_name(self) -> str:
|
|
15
|
+
return "Quality Assurance Kitten 🐱"
|
|
16
|
+
|
|
17
|
+
@property
|
|
18
|
+
def description(self) -> str:
|
|
19
|
+
return "Advanced web browser automation and quality assurance testing using Playwright with VQA capabilities"
|
|
20
|
+
|
|
21
|
+
def get_available_tools(self) -> list[str]:
|
|
22
|
+
"""Get the list of tools available to Web Browser Puppy."""
|
|
23
|
+
return [
|
|
24
|
+
# Core agent tools
|
|
25
|
+
"agent_share_your_reasoning",
|
|
26
|
+
# Browser control and initialization
|
|
27
|
+
"browser_initialize",
|
|
28
|
+
"browser_close",
|
|
29
|
+
"browser_status",
|
|
30
|
+
"browser_new_page",
|
|
31
|
+
"browser_list_pages",
|
|
32
|
+
# Browser navigation
|
|
33
|
+
"browser_navigate",
|
|
34
|
+
"browser_get_page_info",
|
|
35
|
+
"browser_go_back",
|
|
36
|
+
"browser_go_forward",
|
|
37
|
+
"browser_reload",
|
|
38
|
+
"browser_wait_for_load",
|
|
39
|
+
# Element discovery (semantic locators preferred)
|
|
40
|
+
"browser_find_by_role",
|
|
41
|
+
"browser_find_by_text",
|
|
42
|
+
"browser_find_by_label",
|
|
43
|
+
"browser_find_by_placeholder",
|
|
44
|
+
"browser_find_by_test_id",
|
|
45
|
+
"browser_find_buttons",
|
|
46
|
+
"browser_find_links",
|
|
47
|
+
"browser_xpath_query", # Fallback when semantic locators fail
|
|
48
|
+
# Element interactions
|
|
49
|
+
"browser_click",
|
|
50
|
+
"browser_double_click",
|
|
51
|
+
"browser_hover",
|
|
52
|
+
"browser_set_text",
|
|
53
|
+
"browser_get_text",
|
|
54
|
+
"browser_get_value",
|
|
55
|
+
"browser_select_option",
|
|
56
|
+
"browser_check",
|
|
57
|
+
"browser_uncheck",
|
|
58
|
+
# Advanced features
|
|
59
|
+
"browser_execute_js",
|
|
60
|
+
"browser_scroll",
|
|
61
|
+
"browser_scroll_to_element",
|
|
62
|
+
"browser_set_viewport",
|
|
63
|
+
"browser_wait_for_element",
|
|
64
|
+
"browser_highlight_element",
|
|
65
|
+
"browser_clear_highlights",
|
|
66
|
+
# Screenshots and VQA
|
|
67
|
+
"browser_screenshot_analyze",
|
|
68
|
+
# Workflow management
|
|
69
|
+
"browser_save_workflow",
|
|
70
|
+
"browser_list_workflows",
|
|
71
|
+
"browser_read_workflow",
|
|
72
|
+
]
|
|
73
|
+
|
|
74
|
+
def get_system_prompt(self) -> str:
|
|
75
|
+
"""Get Web Browser Puppy's specialized system prompt."""
|
|
76
|
+
return """
|
|
77
|
+
You are Quality Assurance Kitten 🐱, an advanced autonomous browser automation and QA testing agent powered by Playwright!
|
|
78
|
+
|
|
79
|
+
You specialize in:
|
|
80
|
+
🎯 **Quality Assurance Testing** - automated testing of web applications and user workflows
|
|
81
|
+
👁️ **Visual verification** - taking screenshots and analyzing page content for bugs
|
|
82
|
+
🔍 **Element discovery** - finding elements using semantic locators and accessibility best practices
|
|
83
|
+
📝 **Data extraction** - scraping content and gathering information from web pages
|
|
84
|
+
🧪 **Web automation** - filling forms, clicking buttons, navigating sites with precision
|
|
85
|
+
🐛 **Bug detection** - identifying UI issues, broken functionality, and accessibility problems
|
|
86
|
+
|
|
87
|
+
## Core Workflow Philosophy
|
|
88
|
+
|
|
89
|
+
For any browser task, follow this approach:
|
|
90
|
+
1. **Check Existing Workflows**: Use browser_list_workflows to see if similar tasks have been solved before
|
|
91
|
+
2. **Learn from History**: If relevant workflows exist, use browser_read_workflow to review proven strategies
|
|
92
|
+
3. **Plan & Reason**: Use share_your_reasoning to break down complex tasks and explain your approach
|
|
93
|
+
4. **Initialize**: Always start with browser_initialize if browser isn't running
|
|
94
|
+
5. **Navigate**: Use browser_navigate to reach the target page
|
|
95
|
+
6. **Discover**: Use semantic locators (PREFERRED) for element discovery
|
|
96
|
+
7. **Verify**: Use highlighting and screenshots to confirm elements
|
|
97
|
+
8. **Act**: Interact with elements through clicks, typing, etc.
|
|
98
|
+
9. **Validate**: Take screenshots or query DOM to verify actions worked
|
|
99
|
+
10. **Document Success**: Use browser_save_workflow to save successful patterns for future reuse
|
|
100
|
+
|
|
101
|
+
## Tool Usage Guidelines
|
|
102
|
+
|
|
103
|
+
### Browser Initialization
|
|
104
|
+
- **ALWAYS call browser_initialize first** before any other browser operations
|
|
105
|
+
- Choose appropriate settings: headless=False for debugging, headless=True for production
|
|
106
|
+
- Use browser_status to check current state
|
|
107
|
+
|
|
108
|
+
### Element Discovery Best Practices (ACCESSIBILITY FIRST! 🌟)
|
|
109
|
+
- **PREFER semantic locators** - they're more reliable and follow accessibility standards
|
|
110
|
+
- Priority order:
|
|
111
|
+
1. browser_find_by_role (button, link, textbox, heading, etc.)
|
|
112
|
+
2. browser_find_by_label (for form inputs)
|
|
113
|
+
3. browser_find_by_text (for visible text)
|
|
114
|
+
4. browser_find_by_placeholder (for input hints)
|
|
115
|
+
5. browser_find_by_test_id (for test-friendly elements)
|
|
116
|
+
6. browser_xpath_query (ONLY as last resort)
|
|
117
|
+
|
|
118
|
+
### Visual Verification Workflow
|
|
119
|
+
- **Before critical actions**: Use browser_highlight_element to visually confirm
|
|
120
|
+
- **After interactions**: Use browser_screenshot_analyze to verify results
|
|
121
|
+
- **VQA questions**: Ask specific, actionable questions like "Is the login button highlighted?"
|
|
122
|
+
|
|
123
|
+
### Form Input Best Practices
|
|
124
|
+
- **ALWAYS check current values** with browser_get_value before typing
|
|
125
|
+
- Use browser_get_value after typing to verify success
|
|
126
|
+
- This prevents typing loops and gives clear visibility into form state
|
|
127
|
+
- Clear fields when appropriate before entering new text
|
|
128
|
+
|
|
129
|
+
### Error Handling & Troubleshooting
|
|
130
|
+
|
|
131
|
+
**When Element Discovery Fails:**
|
|
132
|
+
1. Try different semantic locators first
|
|
133
|
+
2. Use browser_find_buttons or browser_find_links to see available elements
|
|
134
|
+
3. Take a screenshot with browser_screenshot_analyze to understand the page layout
|
|
135
|
+
4. Only use XPath as absolute last resort
|
|
136
|
+
|
|
137
|
+
**When Page Interactions Fail:**
|
|
138
|
+
1. Check if element is visible with browser_wait_for_element
|
|
139
|
+
2. Scroll element into view with browser_scroll_to_element
|
|
140
|
+
3. Use browser_highlight_element to confirm element location
|
|
141
|
+
4. Try browser_execute_js for complex interactions
|
|
142
|
+
|
|
143
|
+
### JavaScript Execution
|
|
144
|
+
- Use browser_execute_js for:
|
|
145
|
+
- Complex page state checks
|
|
146
|
+
- Custom scrolling behavior
|
|
147
|
+
- Triggering events that standard tools can't handle
|
|
148
|
+
- Accessing browser APIs
|
|
149
|
+
|
|
150
|
+
### Workflow Management 📋
|
|
151
|
+
|
|
152
|
+
**ALWAYS start new tasks by checking for existing workflows!**
|
|
153
|
+
|
|
154
|
+
**At the beginning of any automation task:**
|
|
155
|
+
1. **browser_list_workflows** - Check what workflows are already available
|
|
156
|
+
2. **browser_read_workflow** - If you find a relevant workflow, read it to understand the proven approach
|
|
157
|
+
3. Adapt and apply the successful patterns from existing workflows
|
|
158
|
+
|
|
159
|
+
**When to save workflows:**
|
|
160
|
+
- After successfully completing a complex multi-step task
|
|
161
|
+
- When you discover a reliable pattern for a common website interaction
|
|
162
|
+
- After troubleshooting and finding working solutions for tricky elements
|
|
163
|
+
- Include both the successful steps AND the challenges/solutions you encountered
|
|
164
|
+
|
|
165
|
+
**Workflow naming conventions:**
|
|
166
|
+
- Use descriptive names like "search_and_atc_walmart", "login_to_github", "fill_contact_form"
|
|
167
|
+
- Include the website domain for clarity
|
|
168
|
+
- Focus on the main goal/outcome
|
|
169
|
+
|
|
170
|
+
**What to include in saved workflows:**
|
|
171
|
+
- Step-by-step tool usage with specific parameters
|
|
172
|
+
- Element discovery strategies that worked
|
|
173
|
+
- Common pitfalls and how to avoid them
|
|
174
|
+
- Alternative approaches for edge cases
|
|
175
|
+
- Tips for handling dynamic content
|
|
176
|
+
|
|
177
|
+
### Performance & Best Practices
|
|
178
|
+
- Use appropriate timeouts for element discovery (default 10s is usually fine)
|
|
179
|
+
- Take screenshots strategically - not after every single action
|
|
180
|
+
- Use browser_wait_for_load when navigating to ensure pages are ready
|
|
181
|
+
- Clear highlights when done for clean visual state
|
|
182
|
+
|
|
183
|
+
## Specialized Capabilities
|
|
184
|
+
|
|
185
|
+
🌐 **WCAG 2.2 Level AA Compliance**: Always prioritize accessibility in element discovery
|
|
186
|
+
📸 **Visual Question Answering**: Use browser_screenshot_analyze for intelligent page analysis
|
|
187
|
+
🚀 **Semantic Web Navigation**: Prefer role-based and label-based element discovery
|
|
188
|
+
⚡ **Playwright Power**: Full access to modern browser automation capabilities
|
|
189
|
+
📋 **Workflow Management**: Save, load, and reuse automation patterns for consistency
|
|
190
|
+
|
|
191
|
+
## Important Rules
|
|
192
|
+
|
|
193
|
+
- **ALWAYS check for existing workflows first** - Use browser_list_workflows at the start of new tasks
|
|
194
|
+
- **ALWAYS use browser_initialize before any browser operations**
|
|
195
|
+
- **PREFER semantic locators over XPath** - they're more maintainable and accessible
|
|
196
|
+
- **Use visual verification for critical actions** - highlight elements and take screenshots
|
|
197
|
+
- **Be explicit about your reasoning** - use share_your_reasoning for complex workflows
|
|
198
|
+
- **Handle errors gracefully** - provide helpful debugging information
|
|
199
|
+
- **Follow accessibility best practices** - your automation should work for everyone
|
|
200
|
+
- **Document your successes** - Save working patterns with browser_save_workflow for future reuse
|
|
201
|
+
|
|
202
|
+
Your browser automation should be reliable, maintainable, and accessible. You are a meticulous QA engineer who catches bugs before users do! 🐱✨
|
|
203
|
+
"""
|
|
@@ -114,3 +114,12 @@ class BaseAgent(ABC):
|
|
|
114
114
|
message_hash: Hash of a message that has been compacted/summarized.
|
|
115
115
|
"""
|
|
116
116
|
self._compacted_message_hashes.add(message_hash)
|
|
117
|
+
|
|
118
|
+
def get_model_name(self) -> Optional[str]:
|
|
119
|
+
"""Get pinned model name for this agent, if specified.
|
|
120
|
+
|
|
121
|
+
Returns:
|
|
122
|
+
Model name to use for this agent, or None to use global default.
|
|
123
|
+
"""
|
|
124
|
+
from ..config import get_agent_pinned_model
|
|
125
|
+
return get_agent_pinned_model(self.name)
|
|
@@ -81,7 +81,9 @@ def get_commands_help():
|
|
|
81
81
|
)
|
|
82
82
|
help_lines.append(
|
|
83
83
|
Text("/truncate", style="cyan")
|
|
84
|
-
+ Text(
|
|
84
|
+
+ Text(
|
|
85
|
+
" <N> Truncate message history to N most recent messages (keeping system message)"
|
|
86
|
+
)
|
|
85
87
|
)
|
|
86
88
|
help_lines.append(
|
|
87
89
|
Text("/<unknown>", style="cyan")
|
|
@@ -409,23 +411,33 @@ def handle_command(command: str):
|
|
|
409
411
|
|
|
410
412
|
if command.startswith("/pin_model"):
|
|
411
413
|
# Handle agent model pinning
|
|
414
|
+
import json
|
|
415
|
+
|
|
412
416
|
from code_puppy.agents.json_agent import discover_json_agents
|
|
413
417
|
from code_puppy.command_line.model_picker_completion import load_model_names
|
|
414
|
-
import json
|
|
415
418
|
|
|
416
419
|
tokens = command.split()
|
|
417
420
|
|
|
418
421
|
if len(tokens) != 3:
|
|
419
422
|
emit_warning("Usage: /pin_model <agent-name> <model-name>")
|
|
420
423
|
|
|
421
|
-
# Show available models and
|
|
424
|
+
# Show available models and agents
|
|
422
425
|
available_models = load_model_names()
|
|
423
426
|
json_agents = discover_json_agents()
|
|
424
427
|
|
|
428
|
+
# Get built-in agents
|
|
429
|
+
from code_puppy.agents.agent_manager import get_agent_descriptions
|
|
430
|
+
builtin_agents = get_agent_descriptions()
|
|
431
|
+
|
|
425
432
|
emit_info("Available models:")
|
|
426
433
|
for model in available_models:
|
|
427
434
|
emit_info(f" [cyan]{model}[/cyan]")
|
|
428
435
|
|
|
436
|
+
if builtin_agents:
|
|
437
|
+
emit_info("\nAvailable built-in agents:")
|
|
438
|
+
for agent_name, description in builtin_agents.items():
|
|
439
|
+
emit_info(f" [cyan]{agent_name}[/cyan] - {description}")
|
|
440
|
+
|
|
429
441
|
if json_agents:
|
|
430
442
|
emit_info("\nAvailable JSON agents:")
|
|
431
443
|
for agent_name, agent_path in json_agents.items():
|
|
@@ -442,31 +454,51 @@ def handle_command(command: str):
|
|
|
442
454
|
emit_warning(f"Available models: {', '.join(available_models)}")
|
|
443
455
|
return True
|
|
444
456
|
|
|
445
|
-
# Check
|
|
457
|
+
# Check if this is a JSON agent or a built-in Python agent
|
|
446
458
|
json_agents = discover_json_agents()
|
|
447
|
-
if agent_name not in json_agents:
|
|
448
|
-
emit_error(f"JSON agent '{agent_name}' not found")
|
|
449
459
|
|
|
450
|
-
|
|
460
|
+
# Get list of available built-in agents
|
|
461
|
+
from code_puppy.agents.agent_manager import get_agent_descriptions
|
|
462
|
+
builtin_agents = get_agent_descriptions()
|
|
463
|
+
|
|
464
|
+
is_json_agent = agent_name in json_agents
|
|
465
|
+
is_builtin_agent = agent_name in builtin_agents
|
|
466
|
+
|
|
467
|
+
if not is_json_agent and not is_builtin_agent:
|
|
468
|
+
emit_error(f"Agent '{agent_name}' not found")
|
|
469
|
+
|
|
470
|
+
# Show available agents
|
|
471
|
+
if builtin_agents:
|
|
472
|
+
emit_info("Available built-in agents:")
|
|
473
|
+
for name, desc in builtin_agents.items():
|
|
474
|
+
emit_info(f" [cyan]{name}[/cyan] - {desc}")
|
|
475
|
+
|
|
451
476
|
if json_agents:
|
|
452
|
-
emit_info("
|
|
477
|
+
emit_info("\nAvailable JSON agents:")
|
|
453
478
|
for name, path in json_agents.items():
|
|
454
479
|
emit_info(f" [cyan]{name}[/cyan] ({path})")
|
|
455
480
|
return True
|
|
456
481
|
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
# Load, modify, and save the agent configuration
|
|
482
|
+
# Handle different agent types
|
|
460
483
|
try:
|
|
461
|
-
|
|
462
|
-
|
|
484
|
+
if is_json_agent:
|
|
485
|
+
# Handle JSON agent - modify the JSON file
|
|
486
|
+
agent_file_path = json_agents[agent_name]
|
|
487
|
+
|
|
488
|
+
with open(agent_file_path, "r", encoding="utf-8") as f:
|
|
489
|
+
agent_config = json.load(f)
|
|
463
490
|
|
|
464
|
-
|
|
465
|
-
|
|
491
|
+
# Set the model
|
|
492
|
+
agent_config["model"] = model_name
|
|
466
493
|
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
494
|
+
# Save the updated configuration
|
|
495
|
+
with open(agent_file_path, "w", encoding="utf-8") as f:
|
|
496
|
+
json.dump(agent_config, f, indent=2, ensure_ascii=False)
|
|
497
|
+
|
|
498
|
+
else:
|
|
499
|
+
# Handle built-in Python agent - store in config
|
|
500
|
+
from code_puppy.config import set_agent_pinned_model
|
|
501
|
+
set_agent_pinned_model(agent_name, model_name)
|
|
470
502
|
|
|
471
503
|
emit_success(f"Model '{model_name}' pinned to agent '{agent_name}'")
|
|
472
504
|
|
|
@@ -622,9 +654,11 @@ def handle_command(command: str):
|
|
|
622
654
|
if command.startswith("/truncate"):
|
|
623
655
|
tokens = command.split()
|
|
624
656
|
if len(tokens) != 2:
|
|
625
|
-
emit_error(
|
|
657
|
+
emit_error(
|
|
658
|
+
"Usage: /truncate <N> (where N is the number of messages to keep)"
|
|
659
|
+
)
|
|
626
660
|
return True
|
|
627
|
-
|
|
661
|
+
|
|
628
662
|
try:
|
|
629
663
|
n = int(tokens[1])
|
|
630
664
|
if n < 1:
|
|
@@ -633,23 +667,29 @@ def handle_command(command: str):
|
|
|
633
667
|
except ValueError:
|
|
634
668
|
emit_error("N must be a valid integer")
|
|
635
669
|
return True
|
|
636
|
-
|
|
670
|
+
|
|
637
671
|
from code_puppy.state_management import get_message_history, set_message_history
|
|
638
|
-
|
|
672
|
+
|
|
639
673
|
history = get_message_history()
|
|
640
674
|
if not history:
|
|
641
675
|
emit_warning("No history to truncate yet. Ask me something first!")
|
|
642
676
|
return True
|
|
643
|
-
|
|
677
|
+
|
|
644
678
|
if len(history) <= n:
|
|
645
|
-
emit_info(
|
|
679
|
+
emit_info(
|
|
680
|
+
f"History already has {len(history)} messages, which is <= {n}. Nothing to truncate."
|
|
681
|
+
)
|
|
646
682
|
return True
|
|
647
|
-
|
|
683
|
+
|
|
648
684
|
# Always keep the first message (system message) and then keep the N-1 most recent messages
|
|
649
|
-
truncated_history =
|
|
650
|
-
|
|
685
|
+
truncated_history = (
|
|
686
|
+
[history[0]] + history[-(n - 1) :] if n > 1 else [history[0]]
|
|
687
|
+
)
|
|
688
|
+
|
|
651
689
|
set_message_history(truncated_history)
|
|
652
|
-
emit_success(
|
|
690
|
+
emit_success(
|
|
691
|
+
f"Truncated message history from {len(history)} to {len(truncated_history)} messages (keeping system message and {n - 1} most recent)"
|
|
692
|
+
)
|
|
653
693
|
return True
|
|
654
694
|
|
|
655
695
|
if command in ("/exit", "/quit"):
|
|
@@ -130,7 +130,7 @@ class AddCommand(MCPCommandBase):
|
|
|
130
130
|
"""
|
|
131
131
|
try:
|
|
132
132
|
from code_puppy.config import MCP_SERVERS_FILE
|
|
133
|
-
from code_puppy.
|
|
133
|
+
from code_puppy.mcp_.managed_server import ServerConfig
|
|
134
134
|
|
|
135
135
|
# Extract required fields
|
|
136
136
|
name = config_dict.pop("name")
|
|
@@ -76,7 +76,7 @@ class InstallCommand(MCPCommandBase):
|
|
|
76
76
|
def _install_from_catalog(self, server_name_or_id: str, group_id: str) -> bool:
|
|
77
77
|
"""Install a server directly from the catalog by name or ID."""
|
|
78
78
|
try:
|
|
79
|
-
from code_puppy.
|
|
79
|
+
from code_puppy.mcp_.server_registry_catalog import catalog
|
|
80
80
|
from code_puppy.messaging import emit_prompt
|
|
81
81
|
|
|
82
82
|
from .utils import find_server_id_by_name
|
|
@@ -8,7 +8,7 @@ from typing import List, Optional
|
|
|
8
8
|
from rich.table import Table
|
|
9
9
|
from rich.text import Text
|
|
10
10
|
|
|
11
|
-
from code_puppy.
|
|
11
|
+
from code_puppy.mcp_.managed_server import ServerState
|
|
12
12
|
from code_puppy.messaging import emit_info
|
|
13
13
|
|
|
14
14
|
from .base import MCPCommandBase
|
|
@@ -34,7 +34,7 @@ class SearchCommand(MCPCommandBase):
|
|
|
34
34
|
group_id = self.generate_group_id()
|
|
35
35
|
|
|
36
36
|
try:
|
|
37
|
-
from code_puppy.
|
|
37
|
+
from code_puppy.mcp_.server_registry_catalog import catalog
|
|
38
38
|
|
|
39
39
|
if not args:
|
|
40
40
|
# Show popular servers if no query
|
|
@@ -8,7 +8,7 @@ from typing import List, Optional
|
|
|
8
8
|
|
|
9
9
|
from rich.panel import Panel
|
|
10
10
|
|
|
11
|
-
from code_puppy.
|
|
11
|
+
from code_puppy.mcp_.managed_server import ServerState
|
|
12
12
|
from code_puppy.messaging import emit_info
|
|
13
13
|
|
|
14
14
|
from .base import MCPCommandBase
|
|
@@ -117,7 +117,7 @@ class StatusCommand(MCPCommandBase):
|
|
|
117
117
|
|
|
118
118
|
# Check async lifecycle manager status if available
|
|
119
119
|
try:
|
|
120
|
-
from code_puppy.
|
|
120
|
+
from code_puppy.mcp_.async_lifecycle import get_lifecycle_manager
|
|
121
121
|
|
|
122
122
|
lifecycle_mgr = get_lifecycle_manager()
|
|
123
123
|
if lifecycle_mgr.is_running(server_id):
|
|
@@ -118,7 +118,7 @@ def interactive_server_selection(group_id: str):
|
|
|
118
118
|
# This is a simplified version - the full implementation would have
|
|
119
119
|
# category browsing, search, etc. For now, we'll just show popular servers
|
|
120
120
|
try:
|
|
121
|
-
from code_puppy.
|
|
121
|
+
from code_puppy.mcp_.server_registry_catalog import catalog
|
|
122
122
|
|
|
123
123
|
servers = catalog.get_popular(10)
|
|
124
124
|
if not servers:
|
|
@@ -256,7 +256,7 @@ def install_server_from_catalog(
|
|
|
256
256
|
import os
|
|
257
257
|
|
|
258
258
|
from code_puppy.config import MCP_SERVERS_FILE
|
|
259
|
-
from code_puppy.
|
|
259
|
+
from code_puppy.mcp_.managed_server import ServerConfig
|
|
260
260
|
|
|
261
261
|
# Set environment variables in the current environment
|
|
262
262
|
for var, value in env_vars.items():
|