code-puppy 0.0.358__tar.gz → 0.0.360__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.358 → code_puppy-0.0.360}/PKG-INFO +1 -1
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/agents/agent_qa_kitten.py +13 -13
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/agents/event_stream_handler.py +27 -7
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/config.py +1 -63
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/tools/__init__.py +1 -5
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/tools/browser/__init__.py +0 -4
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/tools/browser/browser_screenshot.py +41 -28
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/tools/browser/terminal_screenshot_tools.py +113 -77
- {code_puppy-0.0.358 → code_puppy-0.0.360}/pyproject.toml +1 -1
- code_puppy-0.0.358/code_puppy/tools/browser/browser_screenshot_vqa.py +0 -195
- code_puppy-0.0.358/code_puppy/tools/browser/vqa_agent.py +0 -194
- {code_puppy-0.0.358 → code_puppy-0.0.360}/.gitignore +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/LICENSE +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/README.md +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/__init__.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/__main__.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/agents/__init__.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/agents/agent_c_reviewer.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/agents/agent_code_puppy.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/agents/agent_code_reviewer.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/agents/agent_cpp_reviewer.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/agents/agent_creator_agent.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/agents/agent_golang_reviewer.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/agents/agent_javascript_reviewer.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/agents/agent_manager.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/agents/agent_pack_leader.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/agents/agent_planning.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/agents/agent_python_programmer.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/agents/agent_python_reviewer.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/agents/agent_qa_expert.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/agents/agent_security_auditor.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/agents/agent_terminal_qa.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/agents/agent_typescript_reviewer.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/agents/base_agent.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/agents/json_agent.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/agents/pack/__init__.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/agents/pack/bloodhound.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/agents/pack/husky.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/agents/pack/retriever.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/agents/pack/shepherd.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/agents/pack/terrier.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/agents/pack/watchdog.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/agents/prompt_reviewer.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/agents/subagent_stream_handler.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/api/__init__.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/api/app.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/api/main.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/api/pty_manager.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/api/routers/__init__.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/api/routers/agents.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/api/routers/commands.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/api/routers/config.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/api/routers/sessions.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/api/templates/terminal.html +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/api/websocket.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/callbacks.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/chatgpt_codex_client.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/claude_cache_client.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/cli_runner.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/__init__.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/add_model_menu.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/attachments.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/autosave_menu.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/clipboard.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/colors_menu.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/command_handler.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/command_registry.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/config_commands.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/core_commands.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/diff_menu.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/file_path_completion.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/load_context_completion.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/mcp/__init__.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/mcp/base.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/mcp/catalog_server_installer.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/mcp/custom_server_form.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/mcp/custom_server_installer.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/mcp/edit_command.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/mcp/handler.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/mcp/help_command.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/mcp/install_command.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/mcp/install_menu.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/mcp/list_command.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/mcp/logs_command.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/mcp/remove_command.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/mcp/restart_command.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/mcp/search_command.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/mcp/start_all_command.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/mcp/start_command.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/mcp/status_command.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/mcp/stop_all_command.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/mcp/stop_command.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/mcp/test_command.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/mcp/utils.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/mcp/wizard_utils.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/mcp_completion.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/model_picker_completion.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/model_settings_menu.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/motd.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/onboarding_slides.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/onboarding_wizard.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/pin_command_completion.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/prompt_toolkit_completion.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/session_commands.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/command_line/utils.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/error_logging.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/gemini_code_assist.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/http_utils.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/keymap.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/main.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/mcp_/__init__.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/mcp_/async_lifecycle.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/mcp_/blocking_startup.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/mcp_/captured_stdio_server.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/mcp_/circuit_breaker.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/mcp_/config_wizard.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/mcp_/dashboard.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/mcp_/error_isolation.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/mcp_/examples/retry_example.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/mcp_/health_monitor.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/mcp_/managed_server.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/mcp_/manager.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/mcp_/mcp_logs.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/mcp_/registry.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/mcp_/retry_manager.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/mcp_/server_registry_catalog.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/mcp_/status_tracker.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/mcp_/system_tools.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/messaging/__init__.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/messaging/bus.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/messaging/commands.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/messaging/markdown_patches.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/messaging/message_queue.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/messaging/messages.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/messaging/queue_console.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/messaging/renderers.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/messaging/rich_renderer.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/messaging/spinner/__init__.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/messaging/spinner/console_spinner.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/messaging/spinner/spinner_base.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/messaging/subagent_console.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/model_factory.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/model_utils.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/models.json +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/models_dev_api.json +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/models_dev_parser.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/plugins/__init__.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/plugins/antigravity_oauth/__init__.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/plugins/antigravity_oauth/accounts.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/plugins/antigravity_oauth/antigravity_model.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/plugins/antigravity_oauth/config.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/plugins/antigravity_oauth/constants.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/plugins/antigravity_oauth/oauth.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/plugins/antigravity_oauth/register_callbacks.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/plugins/antigravity_oauth/storage.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/plugins/antigravity_oauth/test_plugin.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/plugins/antigravity_oauth/token.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/plugins/antigravity_oauth/transport.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/plugins/antigravity_oauth/utils.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/plugins/chatgpt_oauth/__init__.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/plugins/chatgpt_oauth/config.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/plugins/chatgpt_oauth/oauth_flow.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/plugins/chatgpt_oauth/register_callbacks.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/plugins/chatgpt_oauth/test_plugin.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/plugins/chatgpt_oauth/utils.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/plugins/claude_code_oauth/README.md +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/plugins/claude_code_oauth/SETUP.md +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/plugins/claude_code_oauth/__init__.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/plugins/claude_code_oauth/config.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/plugins/claude_code_oauth/register_callbacks.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/plugins/claude_code_oauth/test_plugin.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/plugins/claude_code_oauth/utils.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/plugins/customizable_commands/__init__.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/plugins/customizable_commands/register_callbacks.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/plugins/example_custom_command/README.md +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/plugins/example_custom_command/register_callbacks.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/plugins/file_permission_handler/__init__.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/plugins/file_permission_handler/register_callbacks.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/plugins/frontend_emitter/__init__.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/plugins/frontend_emitter/emitter.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/plugins/frontend_emitter/register_callbacks.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/plugins/oauth_puppy_html.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/plugins/shell_safety/__init__.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/plugins/shell_safety/agent_shell_safety.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/plugins/shell_safety/command_cache.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/plugins/shell_safety/register_callbacks.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/prompts/antigravity_system_prompt.md +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/prompts/codex_system_prompt.md +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/pydantic_patches.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/reopenable_async_client.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/round_robin_model.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/session_storage.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/status_display.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/summarization_agent.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/terminal_utils.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/tools/agent_tools.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/tools/browser/browser_control.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/tools/browser/browser_interactions.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/tools/browser/browser_locators.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/tools/browser/browser_navigation.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/tools/browser/browser_scripts.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/tools/browser/browser_workflows.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/tools/browser/camoufox_manager.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/tools/browser/chromium_terminal_manager.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/tools/browser/terminal_command_tools.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/tools/browser/terminal_tools.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/tools/command_runner.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/tools/common.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/tools/display.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/tools/file_modifications.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/tools/file_operations.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/tools/subagent_context.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/tools/tools_content.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/uvx_detection.py +0 -0
- {code_puppy-0.0.358 → code_puppy-0.0.360}/code_puppy/version_checker.py +0 -0
|
@@ -16,7 +16,7 @@ class QualityAssuranceKittenAgent(BaseAgent):
|
|
|
16
16
|
|
|
17
17
|
@property
|
|
18
18
|
def description(self) -> str:
|
|
19
|
-
return "Advanced web browser automation and quality assurance testing using Playwright with
|
|
19
|
+
return "Advanced web browser automation and quality assurance testing using Playwright with visual analysis capabilities"
|
|
20
20
|
|
|
21
21
|
def get_available_tools(self) -> list[str]:
|
|
22
22
|
"""Get the list of tools available to Web Browser Puppy."""
|
|
@@ -63,8 +63,9 @@ class QualityAssuranceKittenAgent(BaseAgent):
|
|
|
63
63
|
"browser_wait_for_element",
|
|
64
64
|
"browser_highlight_element",
|
|
65
65
|
"browser_clear_highlights",
|
|
66
|
-
# Screenshots
|
|
67
|
-
"
|
|
66
|
+
# Screenshots (returns BinaryContent for direct visual analysis)
|
|
67
|
+
"browser_screenshot_analyze",
|
|
68
|
+
"load_image_for_analysis",
|
|
68
69
|
# Workflow management
|
|
69
70
|
"browser_save_workflow",
|
|
70
71
|
"browser_list_workflows",
|
|
@@ -78,7 +79,7 @@ You are Quality Assurance Kitten 🐱, an advanced autonomous browser automation
|
|
|
78
79
|
|
|
79
80
|
You specialize in:
|
|
80
81
|
🎯 **Quality Assurance Testing** - automated testing of web applications and user workflows
|
|
81
|
-
👁️ **Visual verification** - taking screenshots
|
|
82
|
+
👁️ **Visual verification** - taking screenshots you can directly see and analyze for bugs
|
|
82
83
|
🔍 **Element discovery** - finding elements using semantic locators and accessibility best practices
|
|
83
84
|
📝 **Data extraction** - scraping content and gathering information from web pages
|
|
84
85
|
🧪 **Web automation** - filling forms, clicking buttons, navigating sites with precision
|
|
@@ -117,12 +118,10 @@ For any browser task, follow this approach:
|
|
|
117
118
|
|
|
118
119
|
### Visual Verification Workflow
|
|
119
120
|
- **Before critical actions**: Use browser_highlight_element to visually confirm
|
|
120
|
-
- **After interactions**: Use
|
|
121
|
-
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
- "Is the form filled out correctly?"
|
|
125
|
-
- "What is the main heading text?"
|
|
121
|
+
- **After interactions**: Use browser_screenshot_analyze to verify results
|
|
122
|
+
- The screenshot is returned directly as an image you can see and analyze
|
|
123
|
+
- No need to ask questions - just analyze what you see in the returned image
|
|
124
|
+
- Use load_image_for_analysis to load mockups or reference images for comparison
|
|
126
125
|
|
|
127
126
|
### Form Input Best Practices
|
|
128
127
|
- **ALWAYS check current values** with browser_get_value before typing
|
|
@@ -135,14 +134,15 @@ For any browser task, follow this approach:
|
|
|
135
134
|
**When Element Discovery Fails:**
|
|
136
135
|
1. Try different semantic locators first
|
|
137
136
|
2. Use browser_find_buttons or browser_find_links to see available elements
|
|
138
|
-
3. Take a screenshot with browser_screenshot_analyze to understand the page layout
|
|
137
|
+
3. Take a screenshot with browser_screenshot_analyze to see and understand the page layout
|
|
139
138
|
4. Only use XPath as absolute last resort
|
|
140
139
|
|
|
141
140
|
**When Page Interactions Fail:**
|
|
142
141
|
1. Check if element is visible with browser_wait_for_element
|
|
143
142
|
2. Scroll element into view with browser_scroll_to_element
|
|
144
143
|
3. Use browser_highlight_element to confirm element location
|
|
145
|
-
4.
|
|
144
|
+
4. Take a screenshot with browser_screenshot_analyze to see the actual page state
|
|
145
|
+
5. Try browser_execute_js for complex interactions
|
|
146
146
|
|
|
147
147
|
### JavaScript Execution
|
|
148
148
|
- Use browser_execute_js for:
|
|
@@ -187,7 +187,7 @@ For any browser task, follow this approach:
|
|
|
187
187
|
## Specialized Capabilities
|
|
188
188
|
|
|
189
189
|
🌐 **WCAG 2.2 Level AA Compliance**: Always prioritize accessibility in element discovery
|
|
190
|
-
📸 **Visual
|
|
190
|
+
📸 **Direct Visual Analysis**: Use browser_screenshot_analyze to see and analyze page content directly
|
|
191
191
|
🚀 **Semantic Web Navigation**: Prefer role-based and label-based element discovery
|
|
192
192
|
⚡ **Playwright Power**: Full access to modern browser automation capabilities
|
|
193
193
|
📋 **Workflow Management**: Save, load, and reuse automation patterns for consistency
|
|
@@ -119,6 +119,7 @@ async def event_stream_handler(
|
|
|
119
119
|
tool_parts: set[int] = set() # Track which parts are tool calls
|
|
120
120
|
banner_printed: set[int] = set() # Track if banner was already printed
|
|
121
121
|
token_count: dict[int, int] = {} # Track token count per text/tool part
|
|
122
|
+
tool_names: dict[int, str] = {} # Track tool name per tool part index
|
|
122
123
|
did_stream_anything = False # Track if we streamed any content
|
|
123
124
|
|
|
124
125
|
# Termflow streaming state for text parts
|
|
@@ -203,6 +204,8 @@ async def event_stream_handler(
|
|
|
203
204
|
streaming_parts.add(event.index)
|
|
204
205
|
tool_parts.add(event.index)
|
|
205
206
|
token_count[event.index] = 0 # Initialize token counter
|
|
207
|
+
# Capture tool name from the start event
|
|
208
|
+
tool_names[event.index] = part.tool_name or ""
|
|
206
209
|
# Track tool name for display
|
|
207
210
|
banner_printed.add(
|
|
208
211
|
event.index
|
|
@@ -253,20 +256,36 @@ async def event_stream_handler(
|
|
|
253
256
|
escaped = escape(delta.content_delta)
|
|
254
257
|
console.print(f"[dim]{escaped}[/dim]", end="")
|
|
255
258
|
elif isinstance(delta, ToolCallPartDelta):
|
|
256
|
-
# For tool calls,
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
259
|
+
# For tool calls, estimate tokens from args_delta content
|
|
260
|
+
# args_delta contains the streaming JSON arguments
|
|
261
|
+
args_delta = getattr(delta, "args_delta", "") or ""
|
|
262
|
+
if args_delta:
|
|
263
|
+
# Rough estimate: 4 chars ≈ 1 token (same heuristic as subagent_stream_handler)
|
|
264
|
+
estimated_tokens = max(1, len(args_delta) // 4)
|
|
265
|
+
token_count[event.index] += estimated_tokens
|
|
266
|
+
else:
|
|
267
|
+
# Even empty deltas count as activity
|
|
268
|
+
token_count[event.index] += 1
|
|
269
|
+
|
|
270
|
+
# Update tool name if delta provides more of it
|
|
271
|
+
tool_name_delta = getattr(delta, "tool_name_delta", "") or ""
|
|
272
|
+
if tool_name_delta:
|
|
273
|
+
tool_names[event.index] = (
|
|
274
|
+
tool_names.get(event.index, "") + tool_name_delta
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
# Use stored tool name for display
|
|
278
|
+
tool_name = tool_names.get(event.index, "")
|
|
260
279
|
count = token_count[event.index]
|
|
261
280
|
# Display with tool wrench icon and tool name
|
|
262
281
|
if tool_name:
|
|
263
282
|
console.print(
|
|
264
|
-
f" \U0001f527 Calling {tool_name}... {count}
|
|
283
|
+
f" \U0001f527 Calling {tool_name}... {count} token(s) ",
|
|
265
284
|
end="\r",
|
|
266
285
|
)
|
|
267
286
|
else:
|
|
268
287
|
console.print(
|
|
269
|
-
f" \U0001f527 Calling tool... {count}
|
|
288
|
+
f" \U0001f527 Calling tool... {count} token(s) ",
|
|
270
289
|
end="\r",
|
|
271
290
|
)
|
|
272
291
|
|
|
@@ -311,8 +330,9 @@ async def event_stream_handler(
|
|
|
311
330
|
elif event.index in banner_printed:
|
|
312
331
|
console.print() # Final newline after streaming
|
|
313
332
|
|
|
314
|
-
# Clean up token count
|
|
333
|
+
# Clean up token count and tool names
|
|
315
334
|
token_count.pop(event.index, None)
|
|
335
|
+
tool_names.pop(event.index, None)
|
|
316
336
|
# Clean up all tracking sets
|
|
317
337
|
streaming_parts.discard(event.index)
|
|
318
338
|
thinking_parts.discard(event.index)
|
|
@@ -98,7 +98,6 @@ _CURRENT_AUTOSAVE_ID: Optional[str] = None
|
|
|
98
98
|
_model_validation_cache = {}
|
|
99
99
|
_default_model_cache = None
|
|
100
100
|
_default_vision_model_cache = None
|
|
101
|
-
_default_vqa_model_cache = None
|
|
102
101
|
|
|
103
102
|
|
|
104
103
|
def ensure_config_exists():
|
|
@@ -358,47 +357,6 @@ def _default_vision_model_from_models_json() -> str:
|
|
|
358
357
|
return "gpt-4.1"
|
|
359
358
|
|
|
360
359
|
|
|
361
|
-
def _default_vqa_model_from_models_json() -> str:
|
|
362
|
-
"""Select a default VQA-capable model, preferring vision-ready options."""
|
|
363
|
-
global _default_vqa_model_cache
|
|
364
|
-
|
|
365
|
-
if _default_vqa_model_cache is not None:
|
|
366
|
-
return _default_vqa_model_cache
|
|
367
|
-
|
|
368
|
-
try:
|
|
369
|
-
from code_puppy.model_factory import ModelFactory
|
|
370
|
-
|
|
371
|
-
models_config = ModelFactory.load_config()
|
|
372
|
-
if models_config:
|
|
373
|
-
# Allow explicit VQA hints if present
|
|
374
|
-
for name, config in models_config.items():
|
|
375
|
-
if config.get("supports_vqa"):
|
|
376
|
-
_default_vqa_model_cache = name
|
|
377
|
-
return name
|
|
378
|
-
|
|
379
|
-
# Reuse multimodal heuristics before falling back to generic default
|
|
380
|
-
preferred_candidates = (
|
|
381
|
-
"gpt-4.1",
|
|
382
|
-
"gpt-4.1-mini",
|
|
383
|
-
"claude-4-0-sonnet",
|
|
384
|
-
"gemini-2.5-flash-preview-05-20",
|
|
385
|
-
"gpt-4.1-nano",
|
|
386
|
-
)
|
|
387
|
-
for candidate in preferred_candidates:
|
|
388
|
-
if candidate in models_config:
|
|
389
|
-
_default_vqa_model_cache = candidate
|
|
390
|
-
return candidate
|
|
391
|
-
|
|
392
|
-
_default_vqa_model_cache = _default_model_from_models_json()
|
|
393
|
-
return _default_vqa_model_cache
|
|
394
|
-
|
|
395
|
-
_default_vqa_model_cache = "gpt-4.1"
|
|
396
|
-
return "gpt-4.1"
|
|
397
|
-
except Exception:
|
|
398
|
-
_default_vqa_model_cache = "gpt-4.1"
|
|
399
|
-
return "gpt-4.1"
|
|
400
|
-
|
|
401
|
-
|
|
402
360
|
def _validate_model_exists(model_name: str) -> bool:
|
|
403
361
|
"""Check if a model exists in models.json with caching to avoid redundant calls."""
|
|
404
362
|
global _model_validation_cache
|
|
@@ -424,15 +382,10 @@ def _validate_model_exists(model_name: str) -> bool:
|
|
|
424
382
|
|
|
425
383
|
def clear_model_cache():
|
|
426
384
|
"""Clear the model validation cache. Call this when models.json changes."""
|
|
427
|
-
global
|
|
428
|
-
_model_validation_cache, \
|
|
429
|
-
_default_model_cache, \
|
|
430
|
-
_default_vision_model_cache, \
|
|
431
|
-
_default_vqa_model_cache
|
|
385
|
+
global _model_validation_cache, _default_model_cache, _default_vision_model_cache
|
|
432
386
|
_model_validation_cache.clear()
|
|
433
387
|
_default_model_cache = None
|
|
434
388
|
_default_vision_model_cache = None
|
|
435
|
-
_default_vqa_model_cache = None
|
|
436
389
|
|
|
437
390
|
|
|
438
391
|
def model_supports_setting(model_name: str, setting: str) -> bool:
|
|
@@ -503,21 +456,6 @@ def set_model_name(model: str):
|
|
|
503
456
|
clear_model_cache()
|
|
504
457
|
|
|
505
458
|
|
|
506
|
-
def get_vqa_model_name() -> str:
|
|
507
|
-
"""Return the configured VQA model, falling back to the global model."""
|
|
508
|
-
stored_model = get_value("vqa_model_name")
|
|
509
|
-
if stored_model and _validate_model_exists(stored_model):
|
|
510
|
-
return stored_model
|
|
511
|
-
# Fall back to the global model if no specific VQA model is set
|
|
512
|
-
return get_global_model_name()
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
def set_vqa_model_name(model: str):
|
|
516
|
-
"""Persist the configured VQA model name and refresh caches."""
|
|
517
|
-
set_config_value("vqa_model_name", model or "")
|
|
518
|
-
clear_model_cache()
|
|
519
|
-
|
|
520
|
-
|
|
521
459
|
def get_puppy_token():
|
|
522
460
|
"""Returns the puppy_token from config, or None if not set."""
|
|
523
461
|
return get_value("puppy_token")
|
|
@@ -41,9 +41,6 @@ from code_puppy.tools.browser.browser_navigation import (
|
|
|
41
41
|
from code_puppy.tools.browser.browser_screenshot import (
|
|
42
42
|
register_take_screenshot_and_analyze,
|
|
43
43
|
)
|
|
44
|
-
from code_puppy.tools.browser.browser_screenshot_vqa import (
|
|
45
|
-
register_take_screenshot_and_analyze_vqa,
|
|
46
|
-
)
|
|
47
44
|
from code_puppy.tools.browser.browser_scripts import (
|
|
48
45
|
register_browser_clear_highlights,
|
|
49
46
|
register_browser_highlight_element,
|
|
@@ -146,9 +143,8 @@ TOOL_REGISTRY = {
|
|
|
146
143
|
"browser_wait_for_element": register_wait_for_element,
|
|
147
144
|
"browser_highlight_element": register_browser_highlight_element,
|
|
148
145
|
"browser_clear_highlights": register_browser_clear_highlights,
|
|
149
|
-
# Browser Screenshots
|
|
146
|
+
# Browser Screenshots
|
|
150
147
|
"browser_screenshot_analyze": register_take_screenshot_and_analyze,
|
|
151
|
-
"browser_screenshot_vqa": register_take_screenshot_and_analyze_vqa,
|
|
152
148
|
# Browser Workflows
|
|
153
149
|
"browser_save_workflow": register_save_workflow,
|
|
154
150
|
"browser_list_workflows": register_list_workflows,
|
|
@@ -11,7 +11,6 @@ from .camoufox_manager import (
|
|
|
11
11
|
get_session_browser_manager,
|
|
12
12
|
set_browser_session,
|
|
13
13
|
)
|
|
14
|
-
from .vqa_agent import VisualAnalysisResult, run_vqa_analysis, run_vqa_analysis_stream
|
|
15
14
|
|
|
16
15
|
|
|
17
16
|
def format_terminal_banner(text: str) -> str:
|
|
@@ -35,7 +34,4 @@ __all__ = [
|
|
|
35
34
|
"get_browser_session",
|
|
36
35
|
"get_session_browser_manager",
|
|
37
36
|
"set_browser_session",
|
|
38
|
-
"VisualAnalysisResult",
|
|
39
|
-
"run_vqa_analysis",
|
|
40
|
-
"run_vqa_analysis_stream",
|
|
41
37
|
]
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
"""Screenshot tool for browser automation.
|
|
2
2
|
|
|
3
|
-
Captures screenshots and returns them
|
|
4
|
-
models can directly see and analyze - no separate VQA agent needed.
|
|
3
|
+
Captures screenshots and returns them via ToolReturn with BinaryContent
|
|
4
|
+
so multimodal models can directly see and analyze - no separate VQA agent needed.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
import
|
|
7
|
+
import time
|
|
8
8
|
from datetime import datetime
|
|
9
9
|
from pathlib import Path
|
|
10
10
|
from tempfile import gettempdir, mkdtemp
|
|
11
|
-
from typing import Any, Dict, Optional
|
|
11
|
+
from typing import Any, Dict, Optional, Union
|
|
12
12
|
|
|
13
|
-
from pydantic_ai import RunContext
|
|
13
|
+
from pydantic_ai import BinaryContent, RunContext, ToolReturn
|
|
14
14
|
|
|
15
15
|
from code_puppy.messaging import emit_error, emit_info, emit_success
|
|
16
16
|
from code_puppy.tools.common import generate_group_id
|
|
@@ -54,7 +54,6 @@ async def _capture_screenshot(
|
|
|
54
54
|
result: Dict[str, Any] = {
|
|
55
55
|
"success": True,
|
|
56
56
|
"screenshot_bytes": screenshot_bytes,
|
|
57
|
-
"base64_data": base64.b64encode(screenshot_bytes).decode("utf-8"),
|
|
58
57
|
"timestamp": timestamp,
|
|
59
58
|
}
|
|
60
59
|
|
|
@@ -80,11 +79,11 @@ async def take_screenshot(
|
|
|
80
79
|
full_page: bool = False,
|
|
81
80
|
element_selector: Optional[str] = None,
|
|
82
81
|
save_screenshot: bool = True,
|
|
83
|
-
) -> Dict[str, Any]:
|
|
82
|
+
) -> Union[ToolReturn, Dict[str, Any]]:
|
|
84
83
|
"""Take a screenshot of the browser page.
|
|
85
84
|
|
|
86
|
-
Returns
|
|
87
|
-
|
|
85
|
+
Returns a ToolReturn with BinaryContent so multimodal models can
|
|
86
|
+
directly see and analyze the screenshot.
|
|
88
87
|
|
|
89
88
|
Args:
|
|
90
89
|
full_page: Whether to capture full page or just viewport.
|
|
@@ -92,12 +91,11 @@ async def take_screenshot(
|
|
|
92
91
|
save_screenshot: Whether to save the screenshot to disk.
|
|
93
92
|
|
|
94
93
|
Returns:
|
|
95
|
-
|
|
96
|
-
-
|
|
97
|
-
-
|
|
98
|
-
-
|
|
99
|
-
|
|
100
|
-
- error (str): Error message if unsuccessful.
|
|
94
|
+
ToolReturn containing:
|
|
95
|
+
- return_value: Success message with screenshot path
|
|
96
|
+
- content: List with description and BinaryContent image
|
|
97
|
+
- metadata: Screenshot details (path, target, timestamp)
|
|
98
|
+
Or Dict with error info if failed.
|
|
101
99
|
"""
|
|
102
100
|
target = element_selector or ("full_page" if full_page else "viewport")
|
|
103
101
|
group_id = generate_group_id("browser_screenshot", target)
|
|
@@ -122,15 +120,30 @@ async def take_screenshot(
|
|
|
122
120
|
|
|
123
121
|
if not result["success"]:
|
|
124
122
|
emit_error(result.get("error", "Screenshot failed"), message_group=group_id)
|
|
125
|
-
return result
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
"
|
|
132
|
-
|
|
133
|
-
|
|
123
|
+
return {"success": False, "error": result.get("error")}
|
|
124
|
+
|
|
125
|
+
screenshot_path = result.get("screenshot_path", "(not saved)")
|
|
126
|
+
|
|
127
|
+
# Return as ToolReturn with BinaryContent so the model can SEE the image!
|
|
128
|
+
return ToolReturn(
|
|
129
|
+
return_value=f"Screenshot captured successfully. Saved to: {screenshot_path}",
|
|
130
|
+
content=[
|
|
131
|
+
f"Here's the browser screenshot ({target}):",
|
|
132
|
+
BinaryContent(
|
|
133
|
+
data=result["screenshot_bytes"],
|
|
134
|
+
media_type="image/png",
|
|
135
|
+
),
|
|
136
|
+
"Please analyze what you see and describe any relevant details.",
|
|
137
|
+
],
|
|
138
|
+
metadata={
|
|
139
|
+
"success": True,
|
|
140
|
+
"screenshot_path": screenshot_path,
|
|
141
|
+
"target": target,
|
|
142
|
+
"full_page": full_page,
|
|
143
|
+
"element_selector": element_selector,
|
|
144
|
+
"timestamp": time.time(),
|
|
145
|
+
},
|
|
146
|
+
)
|
|
134
147
|
|
|
135
148
|
except Exception as e:
|
|
136
149
|
error_msg = f"Screenshot failed: {str(e)}"
|
|
@@ -146,19 +159,19 @@ def register_take_screenshot_and_analyze(agent):
|
|
|
146
159
|
context: RunContext,
|
|
147
160
|
full_page: bool = False,
|
|
148
161
|
element_selector: Optional[str] = None,
|
|
149
|
-
) -> Dict[str, Any]:
|
|
162
|
+
) -> Union[ToolReturn, Dict[str, Any]]:
|
|
150
163
|
"""
|
|
151
164
|
Take a screenshot of the browser page.
|
|
152
165
|
|
|
153
|
-
Returns the screenshot
|
|
154
|
-
Use this to see what's displayed in the browser.
|
|
166
|
+
Returns the screenshot via ToolReturn with BinaryContent that you can
|
|
167
|
+
see directly. Use this to see what's displayed in the browser.
|
|
155
168
|
|
|
156
169
|
Args:
|
|
157
170
|
full_page: Capture full page (True) or just viewport (False).
|
|
158
171
|
element_selector: Optional CSS selector to screenshot specific element.
|
|
159
172
|
|
|
160
173
|
Returns:
|
|
161
|
-
|
|
174
|
+
ToolReturn with the screenshot image you can analyze, or error dict.
|
|
162
175
|
"""
|
|
163
176
|
return await take_screenshot(
|
|
164
177
|
full_page=full_page,
|