code-puppy 0.0.369__tar.gz → 0.0.371__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.369 → code_puppy-0.0.371}/PKG-INFO +2 -2
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/agents/__init__.py +6 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/agents/agent_manager.py +205 -1
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/agents/base_agent.py +2 -12
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/chatgpt_codex_client.py +53 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/agent_menu.py +281 -14
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/core_commands.py +3 -3
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/model_picker_completion.py +3 -20
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/config.py +44 -8
- code_puppy-0.0.371/code_puppy/model_switching.py +63 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/model_utils.py +1 -52
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/plugins/antigravity_oauth/register_callbacks.py +15 -8
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/plugins/chatgpt_oauth/register_callbacks.py +2 -2
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/plugins/claude_code_oauth/register_callbacks.py +2 -30
- {code_puppy-0.0.369 → code_puppy-0.0.371}/pyproject.toml +2 -2
- code_puppy-0.0.369/code_puppy/prompts/codex_system_prompt.md +0 -310
- {code_puppy-0.0.369 → code_puppy-0.0.371}/.gitignore +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/LICENSE +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/README.md +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/__init__.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/__main__.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/agents/agent_c_reviewer.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/agents/agent_code_puppy.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/agents/agent_code_reviewer.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/agents/agent_cpp_reviewer.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/agents/agent_creator_agent.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/agents/agent_golang_reviewer.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/agents/agent_javascript_reviewer.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/agents/agent_pack_leader.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/agents/agent_planning.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/agents/agent_python_programmer.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/agents/agent_python_reviewer.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/agents/agent_qa_expert.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/agents/agent_qa_kitten.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/agents/agent_security_auditor.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/agents/agent_terminal_qa.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/agents/agent_typescript_reviewer.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/agents/event_stream_handler.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/agents/json_agent.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/agents/pack/__init__.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/agents/pack/bloodhound.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/agents/pack/husky.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/agents/pack/retriever.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/agents/pack/shepherd.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/agents/pack/terrier.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/agents/pack/watchdog.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/agents/prompt_reviewer.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/agents/subagent_stream_handler.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/api/__init__.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/api/app.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/api/main.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/api/pty_manager.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/api/routers/__init__.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/api/routers/agents.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/api/routers/commands.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/api/routers/config.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/api/routers/sessions.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/api/templates/terminal.html +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/api/websocket.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/callbacks.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/claude_cache_client.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/cli_runner.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/__init__.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/add_model_menu.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/attachments.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/autosave_menu.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/clipboard.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/colors_menu.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/command_handler.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/command_registry.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/config_commands.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/diff_menu.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/file_path_completion.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/load_context_completion.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/mcp/__init__.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/mcp/base.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/mcp/catalog_server_installer.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/mcp/custom_server_form.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/mcp/custom_server_installer.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/mcp/edit_command.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/mcp/handler.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/mcp/help_command.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/mcp/install_command.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/mcp/install_menu.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/mcp/list_command.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/mcp/logs_command.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/mcp/remove_command.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/mcp/restart_command.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/mcp/search_command.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/mcp/start_all_command.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/mcp/start_command.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/mcp/status_command.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/mcp/stop_all_command.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/mcp/stop_command.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/mcp/test_command.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/mcp/utils.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/mcp/wizard_utils.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/mcp_completion.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/model_settings_menu.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/motd.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/onboarding_slides.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/onboarding_wizard.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/pin_command_completion.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/prompt_toolkit_completion.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/session_commands.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/command_line/utils.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/error_logging.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/gemini_code_assist.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/gemini_model.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/http_utils.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/keymap.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/main.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/mcp_/__init__.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/mcp_/async_lifecycle.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/mcp_/blocking_startup.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/mcp_/captured_stdio_server.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/mcp_/circuit_breaker.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/mcp_/config_wizard.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/mcp_/dashboard.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/mcp_/error_isolation.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/mcp_/examples/retry_example.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/mcp_/health_monitor.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/mcp_/managed_server.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/mcp_/manager.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/mcp_/mcp_logs.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/mcp_/registry.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/mcp_/retry_manager.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/mcp_/server_registry_catalog.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/mcp_/status_tracker.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/mcp_/system_tools.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/messaging/__init__.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/messaging/bus.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/messaging/commands.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/messaging/markdown_patches.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/messaging/message_queue.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/messaging/messages.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/messaging/queue_console.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/messaging/renderers.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/messaging/rich_renderer.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/messaging/spinner/__init__.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/messaging/spinner/console_spinner.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/messaging/spinner/spinner_base.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/messaging/subagent_console.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/model_factory.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/models.json +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/models_dev_api.json +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/models_dev_parser.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/plugins/__init__.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/plugins/antigravity_oauth/__init__.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/plugins/antigravity_oauth/accounts.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/plugins/antigravity_oauth/antigravity_model.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/plugins/antigravity_oauth/config.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/plugins/antigravity_oauth/constants.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/plugins/antigravity_oauth/oauth.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/plugins/antigravity_oauth/storage.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/plugins/antigravity_oauth/test_plugin.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/plugins/antigravity_oauth/token.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/plugins/antigravity_oauth/transport.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/plugins/antigravity_oauth/utils.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/plugins/chatgpt_oauth/__init__.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/plugins/chatgpt_oauth/config.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/plugins/chatgpt_oauth/oauth_flow.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/plugins/chatgpt_oauth/test_plugin.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/plugins/chatgpt_oauth/utils.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/plugins/claude_code_oauth/README.md +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/plugins/claude_code_oauth/SETUP.md +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/plugins/claude_code_oauth/__init__.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/plugins/claude_code_oauth/config.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/plugins/claude_code_oauth/test_plugin.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/plugins/claude_code_oauth/utils.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/plugins/customizable_commands/__init__.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/plugins/customizable_commands/register_callbacks.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/plugins/example_custom_command/README.md +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/plugins/example_custom_command/register_callbacks.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/plugins/file_permission_handler/__init__.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/plugins/file_permission_handler/register_callbacks.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/plugins/frontend_emitter/__init__.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/plugins/frontend_emitter/emitter.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/plugins/frontend_emitter/register_callbacks.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/plugins/oauth_puppy_html.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/plugins/shell_safety/__init__.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/plugins/shell_safety/agent_shell_safety.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/plugins/shell_safety/command_cache.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/plugins/shell_safety/register_callbacks.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/prompts/antigravity_system_prompt.md +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/pydantic_patches.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/reopenable_async_client.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/round_robin_model.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/session_storage.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/status_display.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/summarization_agent.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/terminal_utils.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/tools/__init__.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/tools/agent_tools.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/tools/browser/__init__.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/tools/browser/browser_control.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/tools/browser/browser_interactions.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/tools/browser/browser_locators.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/tools/browser/browser_manager.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/tools/browser/browser_navigation.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/tools/browser/browser_screenshot.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/tools/browser/browser_scripts.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/tools/browser/browser_workflows.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/tools/browser/chromium_terminal_manager.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/tools/browser/terminal_command_tools.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/tools/browser/terminal_screenshot_tools.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/tools/browser/terminal_tools.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/tools/command_runner.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/tools/common.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/tools/display.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/tools/file_modifications.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/tools/file_operations.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/tools/subagent_context.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/tools/tools_content.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/code_puppy/uvx_detection.py +0 -0
- {code_puppy-0.0.369 → code_puppy-0.0.371}/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.371
|
|
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
|
|
@@ -24,7 +24,7 @@ Requires-Dist: openai>=1.99.1
|
|
|
24
24
|
Requires-Dist: pillow>=10.0.0
|
|
25
25
|
Requires-Dist: playwright>=1.40.0
|
|
26
26
|
Requires-Dist: prompt-toolkit>=3.0.52
|
|
27
|
-
Requires-Dist: pydantic-ai-slim[anthropic,openai]==1.26.0
|
|
27
|
+
Requires-Dist: pydantic-ai-slim[anthropic,mcp,openai]==1.26.0
|
|
28
28
|
Requires-Dist: pydantic>=2.4.0
|
|
29
29
|
Requires-Dist: pyfiglet>=0.8.post1
|
|
30
30
|
Requires-Dist: python-dotenv>=1.0.0
|
|
@@ -5,9 +5,12 @@ configurations, each with their own system prompts and tool sets.
|
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
from .agent_manager import (
|
|
8
|
+
clone_agent,
|
|
9
|
+
delete_clone_agent,
|
|
8
10
|
get_agent_descriptions,
|
|
9
11
|
get_available_agents,
|
|
10
12
|
get_current_agent,
|
|
13
|
+
is_clone_agent_name,
|
|
11
14
|
load_agent,
|
|
12
15
|
refresh_agents,
|
|
13
16
|
set_current_agent,
|
|
@@ -15,8 +18,11 @@ from .agent_manager import (
|
|
|
15
18
|
from .subagent_stream_handler import subagent_stream_handler
|
|
16
19
|
|
|
17
20
|
__all__ = [
|
|
21
|
+
"clone_agent",
|
|
22
|
+
"delete_clone_agent",
|
|
18
23
|
"get_available_agents",
|
|
19
24
|
"get_current_agent",
|
|
25
|
+
"is_clone_agent_name",
|
|
20
26
|
"set_current_agent",
|
|
21
27
|
"load_agent",
|
|
22
28
|
"get_agent_descriptions",
|
|
@@ -4,6 +4,7 @@ import importlib
|
|
|
4
4
|
import json
|
|
5
5
|
import os
|
|
6
6
|
import pkgutil
|
|
7
|
+
import re
|
|
7
8
|
import uuid
|
|
8
9
|
from pathlib import Path
|
|
9
10
|
from typing import Dict, List, Optional, Type, Union
|
|
@@ -13,7 +14,7 @@ from pydantic_ai.messages import ModelMessage
|
|
|
13
14
|
from code_puppy.agents.base_agent import BaseAgent
|
|
14
15
|
from code_puppy.agents.json_agent import JSONAgent, discover_json_agents
|
|
15
16
|
from code_puppy.callbacks import on_agent_reload
|
|
16
|
-
from code_puppy.messaging import emit_warning
|
|
17
|
+
from code_puppy.messaging import emit_success, emit_warning
|
|
17
18
|
|
|
18
19
|
# Registry of available agents (Python classes and JSON file paths)
|
|
19
20
|
_AGENT_REGISTRY: Dict[str, Union[Type[BaseAgent], str]] = {}
|
|
@@ -467,3 +468,206 @@ def refresh_agents():
|
|
|
467
468
|
# Generate a message group ID for agent refreshing
|
|
468
469
|
message_group_id = str(uuid.uuid4())
|
|
469
470
|
_discover_agents(message_group_id=message_group_id)
|
|
471
|
+
|
|
472
|
+
|
|
473
|
+
_CLONE_NAME_PATTERN = re.compile(r"^(?P<base>.+)-clone-(?P<index>\d+)$")
|
|
474
|
+
_CLONE_DISPLAY_PATTERN = re.compile(r"\s*\(Clone\s+\d+\)$", re.IGNORECASE)
|
|
475
|
+
|
|
476
|
+
|
|
477
|
+
def _strip_clone_suffix(agent_name: str) -> str:
|
|
478
|
+
"""Strip a trailing -clone-N suffix from a name if present."""
|
|
479
|
+
match = _CLONE_NAME_PATTERN.match(agent_name)
|
|
480
|
+
return match.group("base") if match else agent_name
|
|
481
|
+
|
|
482
|
+
|
|
483
|
+
def _strip_clone_display_suffix(display_name: str) -> str:
|
|
484
|
+
"""Remove a trailing "(Clone N)" suffix from display names."""
|
|
485
|
+
cleaned = _CLONE_DISPLAY_PATTERN.sub("", display_name).strip()
|
|
486
|
+
return cleaned or display_name
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
def is_clone_agent_name(agent_name: str) -> bool:
|
|
490
|
+
"""Return True if the agent name looks like a clone."""
|
|
491
|
+
return bool(_CLONE_NAME_PATTERN.match(agent_name))
|
|
492
|
+
|
|
493
|
+
|
|
494
|
+
def _default_display_name(agent_name: str) -> str:
|
|
495
|
+
"""Build a default display name from an agent name."""
|
|
496
|
+
title = agent_name.title()
|
|
497
|
+
return f"{title} 🤖"
|
|
498
|
+
|
|
499
|
+
|
|
500
|
+
def _build_clone_display_name(display_name: str, clone_index: int) -> str:
|
|
501
|
+
"""Build a clone display name based on the source display name."""
|
|
502
|
+
base_name = _strip_clone_display_suffix(display_name)
|
|
503
|
+
return f"{base_name} (Clone {clone_index})"
|
|
504
|
+
|
|
505
|
+
|
|
506
|
+
def _filter_available_tools(tool_names: List[str]) -> List[str]:
|
|
507
|
+
"""Filter a tool list to only available tool names."""
|
|
508
|
+
from code_puppy.tools import get_available_tool_names
|
|
509
|
+
|
|
510
|
+
available_tools = set(get_available_tool_names())
|
|
511
|
+
return [tool for tool in tool_names if tool in available_tools]
|
|
512
|
+
|
|
513
|
+
|
|
514
|
+
def _next_clone_index(
|
|
515
|
+
base_name: str, existing_names: set[str], agents_dir: Path
|
|
516
|
+
) -> int:
|
|
517
|
+
"""Compute the next clone index for a base name."""
|
|
518
|
+
clone_pattern = re.compile(rf"^{re.escape(base_name)}-clone-(\\d+)$")
|
|
519
|
+
indices = []
|
|
520
|
+
for name in existing_names:
|
|
521
|
+
match = clone_pattern.match(name)
|
|
522
|
+
if match:
|
|
523
|
+
indices.append(int(match.group(1)))
|
|
524
|
+
|
|
525
|
+
next_index = max(indices, default=0) + 1
|
|
526
|
+
while True:
|
|
527
|
+
clone_name = f"{base_name}-clone-{next_index}"
|
|
528
|
+
clone_path = agents_dir / f"{clone_name}.json"
|
|
529
|
+
if clone_name not in existing_names and not clone_path.exists():
|
|
530
|
+
return next_index
|
|
531
|
+
next_index += 1
|
|
532
|
+
|
|
533
|
+
|
|
534
|
+
def clone_agent(agent_name: str) -> Optional[str]:
|
|
535
|
+
"""Clone an agent definition into the user agents directory.
|
|
536
|
+
|
|
537
|
+
Args:
|
|
538
|
+
agent_name: Source agent name to clone.
|
|
539
|
+
|
|
540
|
+
Returns:
|
|
541
|
+
The cloned agent name, or None if cloning failed.
|
|
542
|
+
"""
|
|
543
|
+
# Generate a message group ID for agent cloning
|
|
544
|
+
message_group_id = str(uuid.uuid4())
|
|
545
|
+
_discover_agents(message_group_id=message_group_id)
|
|
546
|
+
|
|
547
|
+
agent_ref = _AGENT_REGISTRY.get(agent_name)
|
|
548
|
+
if agent_ref is None:
|
|
549
|
+
emit_warning(f"Agent '{agent_name}' not found for cloning.")
|
|
550
|
+
return None
|
|
551
|
+
|
|
552
|
+
from ..config import get_agent_pinned_model, get_user_agents_directory
|
|
553
|
+
|
|
554
|
+
agents_dir = Path(get_user_agents_directory())
|
|
555
|
+
base_name = _strip_clone_suffix(agent_name)
|
|
556
|
+
existing_names = set(_AGENT_REGISTRY.keys())
|
|
557
|
+
clone_index = _next_clone_index(base_name, existing_names, agents_dir)
|
|
558
|
+
clone_name = f"{base_name}-clone-{clone_index}"
|
|
559
|
+
clone_path = agents_dir / f"{clone_name}.json"
|
|
560
|
+
|
|
561
|
+
try:
|
|
562
|
+
if isinstance(agent_ref, str):
|
|
563
|
+
with open(agent_ref, "r", encoding="utf-8") as f:
|
|
564
|
+
source_config = json.load(f)
|
|
565
|
+
|
|
566
|
+
source_display_name = source_config.get("display_name")
|
|
567
|
+
if not source_display_name:
|
|
568
|
+
source_display_name = _default_display_name(base_name)
|
|
569
|
+
|
|
570
|
+
clone_config = dict(source_config)
|
|
571
|
+
clone_config["name"] = clone_name
|
|
572
|
+
clone_config["display_name"] = _build_clone_display_name(
|
|
573
|
+
source_display_name, clone_index
|
|
574
|
+
)
|
|
575
|
+
|
|
576
|
+
tools = source_config.get("tools", [])
|
|
577
|
+
clone_config["tools"] = (
|
|
578
|
+
_filter_available_tools(tools) if isinstance(tools, list) else []
|
|
579
|
+
)
|
|
580
|
+
|
|
581
|
+
if not clone_config.get("model"):
|
|
582
|
+
clone_config.pop("model", None)
|
|
583
|
+
else:
|
|
584
|
+
agent_instance = agent_ref()
|
|
585
|
+
clone_config = {
|
|
586
|
+
"name": clone_name,
|
|
587
|
+
"display_name": _build_clone_display_name(
|
|
588
|
+
agent_instance.display_name, clone_index
|
|
589
|
+
),
|
|
590
|
+
"description": agent_instance.description,
|
|
591
|
+
"system_prompt": agent_instance.get_system_prompt(),
|
|
592
|
+
"tools": _filter_available_tools(agent_instance.get_available_tools()),
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
user_prompt = agent_instance.get_user_prompt()
|
|
596
|
+
if user_prompt is not None:
|
|
597
|
+
clone_config["user_prompt"] = user_prompt
|
|
598
|
+
|
|
599
|
+
tools_config = agent_instance.get_tools_config()
|
|
600
|
+
if tools_config is not None:
|
|
601
|
+
clone_config["tools_config"] = tools_config
|
|
602
|
+
|
|
603
|
+
pinned_model = get_agent_pinned_model(agent_instance.name)
|
|
604
|
+
if pinned_model:
|
|
605
|
+
clone_config["model"] = pinned_model
|
|
606
|
+
except Exception as exc:
|
|
607
|
+
emit_warning(f"Failed to build clone for '{agent_name}': {exc}")
|
|
608
|
+
return None
|
|
609
|
+
|
|
610
|
+
if clone_path.exists():
|
|
611
|
+
emit_warning(f"Clone target '{clone_name}' already exists.")
|
|
612
|
+
return None
|
|
613
|
+
|
|
614
|
+
try:
|
|
615
|
+
with open(clone_path, "w", encoding="utf-8") as f:
|
|
616
|
+
json.dump(clone_config, f, indent=2, ensure_ascii=False)
|
|
617
|
+
emit_success(f"Cloned '{agent_name}' to '{clone_name}'.")
|
|
618
|
+
return clone_name
|
|
619
|
+
except Exception as exc:
|
|
620
|
+
emit_warning(f"Failed to write clone file '{clone_path}': {exc}")
|
|
621
|
+
return None
|
|
622
|
+
|
|
623
|
+
|
|
624
|
+
def delete_clone_agent(agent_name: str) -> bool:
|
|
625
|
+
"""Delete a cloned JSON agent definition.
|
|
626
|
+
|
|
627
|
+
Args:
|
|
628
|
+
agent_name: Clone agent name to delete.
|
|
629
|
+
|
|
630
|
+
Returns:
|
|
631
|
+
True if the clone was deleted, False otherwise.
|
|
632
|
+
"""
|
|
633
|
+
message_group_id = str(uuid.uuid4())
|
|
634
|
+
_discover_agents(message_group_id=message_group_id)
|
|
635
|
+
|
|
636
|
+
if not is_clone_agent_name(agent_name):
|
|
637
|
+
emit_warning(f"Agent '{agent_name}' is not a clone.")
|
|
638
|
+
return False
|
|
639
|
+
|
|
640
|
+
if get_current_agent_name() == agent_name:
|
|
641
|
+
emit_warning("Cannot delete the active agent. Switch agents first.")
|
|
642
|
+
return False
|
|
643
|
+
|
|
644
|
+
agent_ref = _AGENT_REGISTRY.get(agent_name)
|
|
645
|
+
if agent_ref is None:
|
|
646
|
+
emit_warning(f"Clone '{agent_name}' not found.")
|
|
647
|
+
return False
|
|
648
|
+
|
|
649
|
+
if not isinstance(agent_ref, str):
|
|
650
|
+
emit_warning(f"Clone '{agent_name}' is not a JSON agent.")
|
|
651
|
+
return False
|
|
652
|
+
|
|
653
|
+
clone_path = Path(agent_ref)
|
|
654
|
+
if not clone_path.exists():
|
|
655
|
+
emit_warning(f"Clone file for '{agent_name}' does not exist.")
|
|
656
|
+
return False
|
|
657
|
+
|
|
658
|
+
from ..config import get_user_agents_directory
|
|
659
|
+
|
|
660
|
+
agents_dir = Path(get_user_agents_directory()).resolve()
|
|
661
|
+
if clone_path.resolve().parent != agents_dir:
|
|
662
|
+
emit_warning(f"Refusing to delete non-user clone '{agent_name}'.")
|
|
663
|
+
return False
|
|
664
|
+
|
|
665
|
+
try:
|
|
666
|
+
clone_path.unlink()
|
|
667
|
+
emit_success(f"Deleted clone '{agent_name}'.")
|
|
668
|
+
_AGENT_REGISTRY.pop(agent_name, None)
|
|
669
|
+
_AGENT_HISTORIES.pop(agent_name, None)
|
|
670
|
+
return True
|
|
671
|
+
except Exception as exc:
|
|
672
|
+
emit_warning(f"Failed to delete clone '{agent_name}': {exc}")
|
|
673
|
+
return False
|
|
@@ -378,10 +378,8 @@ class BaseAgent(ABC):
|
|
|
378
378
|
try:
|
|
379
379
|
from code_puppy.model_utils import (
|
|
380
380
|
get_antigravity_instructions,
|
|
381
|
-
get_chatgpt_codex_instructions,
|
|
382
381
|
get_claude_code_instructions,
|
|
383
382
|
is_antigravity_model,
|
|
384
|
-
is_chatgpt_codex_model,
|
|
385
383
|
is_claude_code_model,
|
|
386
384
|
)
|
|
387
385
|
|
|
@@ -393,11 +391,6 @@ class BaseAgent(ABC):
|
|
|
393
391
|
# The full system prompt is already in the message history
|
|
394
392
|
instructions = get_claude_code_instructions()
|
|
395
393
|
total_tokens += self.estimate_token_count(instructions)
|
|
396
|
-
elif is_chatgpt_codex_model(model_name):
|
|
397
|
-
# For ChatGPT Codex models, only count the short fixed instructions
|
|
398
|
-
# The full system prompt is already in the message history
|
|
399
|
-
instructions = get_chatgpt_codex_instructions()
|
|
400
|
-
total_tokens += self.estimate_token_count(instructions)
|
|
401
394
|
elif is_antigravity_model(model_name):
|
|
402
395
|
# For Antigravity models, only count the short fixed instructions
|
|
403
396
|
# The full system prompt is already in the message history
|
|
@@ -1568,14 +1561,11 @@ class BaseAgent(ABC):
|
|
|
1568
1561
|
# Handle claude-code, chatgpt-codex, and antigravity models: prepend system prompt to first user message
|
|
1569
1562
|
from code_puppy.model_utils import (
|
|
1570
1563
|
is_antigravity_model,
|
|
1571
|
-
is_chatgpt_codex_model,
|
|
1572
1564
|
is_claude_code_model,
|
|
1573
1565
|
)
|
|
1574
1566
|
|
|
1575
|
-
if (
|
|
1576
|
-
|
|
1577
|
-
or is_chatgpt_codex_model(self.get_model_name())
|
|
1578
|
-
or is_antigravity_model(self.get_model_name())
|
|
1567
|
+
if is_claude_code_model(self.get_model_name()) or is_antigravity_model(
|
|
1568
|
+
self.get_model_name()
|
|
1579
1569
|
):
|
|
1580
1570
|
if len(self.get_message_history()) == 0:
|
|
1581
1571
|
system_prompt = self.get_system_prompt()
|
|
@@ -156,6 +156,59 @@ class ChatGPTCodexAsyncClient(httpx.AsyncClient):
|
|
|
156
156
|
}
|
|
157
157
|
modified = True
|
|
158
158
|
|
|
159
|
+
# When `store=false` (Codex requirement), the backend does NOT persist input items.
|
|
160
|
+
# That means any later request that tries to reference a previous item by id will 404.
|
|
161
|
+
# We defensively strip reference-style items (especially reasoning_content) to avoid:
|
|
162
|
+
# "Item with id 'rs_...' not found. Items are not persisted when store is false."
|
|
163
|
+
input_items = data.get("input")
|
|
164
|
+
if data.get("store") is False and isinstance(input_items, list):
|
|
165
|
+
original_len = len(input_items)
|
|
166
|
+
|
|
167
|
+
def _looks_like_unpersisted_reference(it: dict) -> bool:
|
|
168
|
+
it_id = it.get("id")
|
|
169
|
+
if it_id in {"reasoning_content", "rs_reasoning_content"}:
|
|
170
|
+
return True
|
|
171
|
+
|
|
172
|
+
# Common reference-ish shapes: {"type": "input_item_reference", "id": "..."}
|
|
173
|
+
it_type = it.get("type")
|
|
174
|
+
if it_type in {"input_item_reference", "item_reference", "reference"}:
|
|
175
|
+
return True
|
|
176
|
+
|
|
177
|
+
# Ultra-conservative: if it's basically just an id (no actual content), drop it.
|
|
178
|
+
# A legit content item will typically have fields like `content`, `text`, `role`, etc.
|
|
179
|
+
non_id_keys = {k for k in it.keys() if k not in {"id", "type"}}
|
|
180
|
+
if not non_id_keys and isinstance(it_id, str) and it_id:
|
|
181
|
+
return True
|
|
182
|
+
|
|
183
|
+
return False
|
|
184
|
+
|
|
185
|
+
filtered: list[object] = []
|
|
186
|
+
for item in input_items:
|
|
187
|
+
if isinstance(item, dict) and _looks_like_unpersisted_reference(item):
|
|
188
|
+
modified = True
|
|
189
|
+
continue
|
|
190
|
+
filtered.append(item)
|
|
191
|
+
|
|
192
|
+
if len(filtered) != original_len:
|
|
193
|
+
data["input"] = filtered
|
|
194
|
+
|
|
195
|
+
# Normalize invalid input IDs (Codex expects reasoning ids to start with "rs_")
|
|
196
|
+
# Note: this is only safe for actual content items, NOT references.
|
|
197
|
+
input_items = data.get("input")
|
|
198
|
+
if isinstance(input_items, list):
|
|
199
|
+
for item in input_items:
|
|
200
|
+
if not isinstance(item, dict):
|
|
201
|
+
continue
|
|
202
|
+
item_id = item.get("id")
|
|
203
|
+
if (
|
|
204
|
+
isinstance(item_id, str)
|
|
205
|
+
and item_id
|
|
206
|
+
and "reasoning" in item_id
|
|
207
|
+
and not item_id.startswith("rs_")
|
|
208
|
+
):
|
|
209
|
+
item["id"] = f"rs_{item_id}"
|
|
210
|
+
modified = True
|
|
211
|
+
|
|
159
212
|
# Remove unsupported parameters
|
|
160
213
|
# Note: verbosity should be under "text" object, not top-level
|
|
161
214
|
unsupported_params = ["max_output_tokens", "max_tokens", "verbosity"]
|