code-puppy 0.0.325__tar.gz → 0.0.327__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.325 → code_puppy-0.0.327}/PKG-INFO +30 -1
- {code_puppy-0.0.325 → code_puppy-0.0.327}/README.md +29 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/agents/base_agent.py +11 -63
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/cli_runner.py +1 -2
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/config_commands.py +24 -1
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/keymap.py +2 -8
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/tools/command_runner.py +21 -48
- {code_puppy-0.0.325 → code_puppy-0.0.327}/pyproject.toml +1 -1
- {code_puppy-0.0.325 → code_puppy-0.0.327}/.gitignore +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/LICENSE +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/__init__.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/__main__.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/agents/__init__.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/agents/agent_c_reviewer.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/agents/agent_code_puppy.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/agents/agent_code_reviewer.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/agents/agent_cpp_reviewer.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/agents/agent_creator_agent.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/agents/agent_golang_reviewer.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/agents/agent_javascript_reviewer.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/agents/agent_manager.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/agents/agent_planning.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/agents/agent_python_programmer.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/agents/agent_python_reviewer.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/agents/agent_qa_expert.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/agents/agent_qa_kitten.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/agents/agent_security_auditor.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/agents/agent_typescript_reviewer.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/agents/json_agent.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/agents/prompt_reviewer.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/callbacks.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/chatgpt_codex_client.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/claude_cache_client.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/__init__.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/add_model_menu.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/attachments.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/autosave_menu.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/colors_menu.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/command_handler.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/command_registry.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/core_commands.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/diff_menu.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/file_path_completion.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/load_context_completion.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/mcp/__init__.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/mcp/add_command.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/mcp/base.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/mcp/catalog_server_installer.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/mcp/custom_server_form.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/mcp/custom_server_installer.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/mcp/edit_command.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/mcp/handler.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/mcp/help_command.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/mcp/install_command.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/mcp/install_menu.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/mcp/list_command.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/mcp/logs_command.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/mcp/remove_command.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/mcp/restart_command.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/mcp/search_command.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/mcp/start_all_command.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/mcp/start_command.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/mcp/status_command.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/mcp/stop_all_command.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/mcp/stop_command.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/mcp/test_command.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/mcp/utils.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/mcp/wizard_utils.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/mcp_completion.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/model_picker_completion.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/model_settings_menu.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/motd.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/pin_command_completion.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/prompt_toolkit_completion.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/session_commands.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/utils.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/config.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/error_logging.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/gemini_code_assist.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/http_utils.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/main.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/mcp_/__init__.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/mcp_/async_lifecycle.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/mcp_/blocking_startup.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/mcp_/captured_stdio_server.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/mcp_/circuit_breaker.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/mcp_/config_wizard.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/mcp_/dashboard.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/mcp_/error_isolation.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/mcp_/examples/retry_example.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/mcp_/health_monitor.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/mcp_/managed_server.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/mcp_/manager.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/mcp_/mcp_logs.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/mcp_/registry.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/mcp_/retry_manager.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/mcp_/server_registry_catalog.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/mcp_/status_tracker.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/mcp_/system_tools.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/messaging/__init__.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/messaging/bus.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/messaging/commands.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/messaging/markdown_patches.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/messaging/message_queue.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/messaging/messages.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/messaging/queue_console.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/messaging/renderers.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/messaging/rich_renderer.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/messaging/spinner/__init__.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/messaging/spinner/console_spinner.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/messaging/spinner/spinner_base.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/model_factory.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/model_utils.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/models.json +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/models_dev_api.json +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/models_dev_parser.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/plugins/__init__.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/plugins/chatgpt_oauth/__init__.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/plugins/chatgpt_oauth/config.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/plugins/chatgpt_oauth/oauth_flow.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/plugins/chatgpt_oauth/register_callbacks.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/plugins/chatgpt_oauth/test_plugin.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/plugins/chatgpt_oauth/utils.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/plugins/claude_code_oauth/README.md +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/plugins/claude_code_oauth/SETUP.md +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/plugins/claude_code_oauth/__init__.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/plugins/claude_code_oauth/config.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/plugins/claude_code_oauth/register_callbacks.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/plugins/claude_code_oauth/test_plugin.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/plugins/claude_code_oauth/utils.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/plugins/customizable_commands/__init__.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/plugins/customizable_commands/register_callbacks.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/plugins/example_custom_command/README.md +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/plugins/example_custom_command/register_callbacks.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/plugins/file_permission_handler/__init__.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/plugins/file_permission_handler/register_callbacks.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/plugins/oauth_puppy_html.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/plugins/shell_safety/__init__.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/plugins/shell_safety/agent_shell_safety.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/plugins/shell_safety/command_cache.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/plugins/shell_safety/register_callbacks.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/prompts/codex_system_prompt.md +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/pydantic_patches.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/reopenable_async_client.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/round_robin_model.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/session_storage.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/status_display.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/summarization_agent.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/terminal_utils.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/tools/__init__.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/tools/agent_tools.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/tools/browser/__init__.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/tools/browser/browser_control.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/tools/browser/browser_interactions.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/tools/browser/browser_locators.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/tools/browser/browser_navigation.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/tools/browser/browser_screenshot.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/tools/browser/browser_scripts.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/tools/browser/browser_workflows.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/tools/browser/camoufox_manager.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/tools/browser/vqa_agent.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/tools/common.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/tools/file_modifications.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/tools/file_operations.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/tools/tools_content.py +0 -0
- {code_puppy-0.0.325 → code_puppy-0.0.327}/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.327
|
|
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
|
|
@@ -100,6 +100,8 @@ uvx code-puppy -i
|
|
|
100
100
|
|
|
101
101
|
### UV (Recommended)
|
|
102
102
|
|
|
103
|
+
#### macOS / Linux
|
|
104
|
+
|
|
103
105
|
```bash
|
|
104
106
|
# Install UV if you don't have it
|
|
105
107
|
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
@@ -112,6 +114,33 @@ source ~/.zshrc # or ~/.bashrc
|
|
|
112
114
|
uvx code-puppy -i
|
|
113
115
|
```
|
|
114
116
|
|
|
117
|
+
#### Windows
|
|
118
|
+
|
|
119
|
+
On Windows, we recommend installing code-puppy as a global tool for the best experience with keyboard shortcuts (Ctrl+C/Ctrl+X cancellation):
|
|
120
|
+
|
|
121
|
+
```powershell
|
|
122
|
+
# Install UV if you don't have it (run in PowerShell as Admin)
|
|
123
|
+
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
|
|
124
|
+
|
|
125
|
+
# Install code-puppy as a global tool
|
|
126
|
+
uv tool install code-puppy
|
|
127
|
+
|
|
128
|
+
# Run code-puppy
|
|
129
|
+
code-puppy -i
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
**Why `uv tool install` on Windows?** Running with `uvx` creates an extra process layer that can interfere with keyboard signal handling (Ctrl+C, Ctrl+X). Installing as a tool runs code-puppy directly for reliable cancellation.
|
|
133
|
+
|
|
134
|
+
#### Upgrading
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
# Upgrade code-puppy to the latest version
|
|
138
|
+
uv tool upgrade code-puppy
|
|
139
|
+
|
|
140
|
+
# Or upgrade all installed tools
|
|
141
|
+
uv tool upgrade --all
|
|
142
|
+
```
|
|
143
|
+
|
|
115
144
|
UV will automatically download the latest compatible Python version (3.11+) if your system doesn't have one.
|
|
116
145
|
|
|
117
146
|
### pip (Alternative)
|
|
@@ -61,6 +61,8 @@ uvx code-puppy -i
|
|
|
61
61
|
|
|
62
62
|
### UV (Recommended)
|
|
63
63
|
|
|
64
|
+
#### macOS / Linux
|
|
65
|
+
|
|
64
66
|
```bash
|
|
65
67
|
# Install UV if you don't have it
|
|
66
68
|
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
@@ -73,6 +75,33 @@ source ~/.zshrc # or ~/.bashrc
|
|
|
73
75
|
uvx code-puppy -i
|
|
74
76
|
```
|
|
75
77
|
|
|
78
|
+
#### Windows
|
|
79
|
+
|
|
80
|
+
On Windows, we recommend installing code-puppy as a global tool for the best experience with keyboard shortcuts (Ctrl+C/Ctrl+X cancellation):
|
|
81
|
+
|
|
82
|
+
```powershell
|
|
83
|
+
# Install UV if you don't have it (run in PowerShell as Admin)
|
|
84
|
+
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
|
|
85
|
+
|
|
86
|
+
# Install code-puppy as a global tool
|
|
87
|
+
uv tool install code-puppy
|
|
88
|
+
|
|
89
|
+
# Run code-puppy
|
|
90
|
+
code-puppy -i
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**Why `uv tool install` on Windows?** Running with `uvx` creates an extra process layer that can interfere with keyboard signal handling (Ctrl+C, Ctrl+X). Installing as a tool runs code-puppy directly for reliable cancellation.
|
|
94
|
+
|
|
95
|
+
#### Upgrading
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
# Upgrade code-puppy to the latest version
|
|
99
|
+
uv tool upgrade code-puppy
|
|
100
|
+
|
|
101
|
+
# Or upgrade all installed tools
|
|
102
|
+
uv tool upgrade --all
|
|
103
|
+
```
|
|
104
|
+
|
|
76
105
|
UV will automatically download the latest compatible Python version (3.11+) if your system doesn't have one.
|
|
77
106
|
|
|
78
107
|
### pip (Alternative)
|
|
@@ -4,7 +4,6 @@ import asyncio
|
|
|
4
4
|
import json
|
|
5
5
|
import math
|
|
6
6
|
import signal
|
|
7
|
-
import sys
|
|
8
7
|
import threading
|
|
9
8
|
import uuid
|
|
10
9
|
from abc import ABC, abstractmethod
|
|
@@ -1957,69 +1956,27 @@ class BaseAgent(ABC):
|
|
|
1957
1956
|
from code_puppy.keymap import get_cancel_agent_display_name
|
|
1958
1957
|
|
|
1959
1958
|
cancel_key = get_cancel_agent_display_name()
|
|
1960
|
-
|
|
1961
|
-
# On Windows, we use keyboard listener, so SIGINT might still fire
|
|
1962
|
-
# but we handle cancellation via the key listener
|
|
1963
|
-
pass # Silent on Windows - the key listener handles it
|
|
1964
|
-
else:
|
|
1965
|
-
emit_info(f"Use {cancel_key} to cancel the agent task.")
|
|
1959
|
+
emit_info(f"Use {cancel_key} to cancel the agent task.")
|
|
1966
1960
|
|
|
1967
1961
|
original_handler = None
|
|
1968
1962
|
key_listener_stop_event = None
|
|
1969
1963
|
_key_listener_thread = None
|
|
1970
|
-
_windows_ctrl_handler = None # Store reference to prevent garbage collection
|
|
1971
1964
|
|
|
1972
1965
|
try:
|
|
1973
|
-
if
|
|
1974
|
-
#
|
|
1975
|
-
import ctypes
|
|
1976
|
-
|
|
1977
|
-
# Define the handler function type
|
|
1978
|
-
HANDLER_ROUTINE = ctypes.WINFUNCTYPE(ctypes.c_bool, ctypes.c_ulong)
|
|
1979
|
-
|
|
1980
|
-
def windows_ctrl_handler(ctrl_type):
|
|
1981
|
-
"""Handle Windows console control events."""
|
|
1982
|
-
CTRL_C_EVENT = 0
|
|
1983
|
-
CTRL_BREAK_EVENT = 1
|
|
1984
|
-
|
|
1985
|
-
if ctrl_type in (CTRL_C_EVENT, CTRL_BREAK_EVENT):
|
|
1986
|
-
# Check if we're awaiting user input
|
|
1987
|
-
if is_awaiting_user_input():
|
|
1988
|
-
return False # Let default handler run
|
|
1989
|
-
|
|
1990
|
-
# Schedule agent cancellation
|
|
1991
|
-
schedule_agent_cancel()
|
|
1992
|
-
return True # We handled it, don't terminate
|
|
1993
|
-
|
|
1994
|
-
return False # Let other handlers process it
|
|
1995
|
-
|
|
1996
|
-
# Create the callback - must keep reference alive!
|
|
1997
|
-
_windows_ctrl_handler = HANDLER_ROUTINE(windows_ctrl_handler)
|
|
1998
|
-
|
|
1999
|
-
# Register the handler
|
|
2000
|
-
kernel32 = ctypes.windll.kernel32
|
|
2001
|
-
if not kernel32.SetConsoleCtrlHandler(_windows_ctrl_handler, True):
|
|
2002
|
-
emit_warning("Failed to set Windows Ctrl+C handler")
|
|
2003
|
-
|
|
2004
|
-
# Also spawn keyboard listener for Ctrl+X (shell cancel) and other keys
|
|
2005
|
-
key_listener_stop_event = threading.Event()
|
|
2006
|
-
_key_listener_thread = self._spawn_ctrl_x_key_listener(
|
|
2007
|
-
key_listener_stop_event,
|
|
2008
|
-
on_escape=lambda: None, # Ctrl+X handled by command_runner
|
|
2009
|
-
on_cancel_agent=None, # Ctrl+C handled by SetConsoleCtrlHandler above
|
|
2010
|
-
)
|
|
2011
|
-
elif cancel_agent_uses_signal():
|
|
2012
|
-
# Unix with Ctrl+C: Use SIGINT-based cancellation
|
|
1966
|
+
if cancel_agent_uses_signal():
|
|
1967
|
+
# Use SIGINT-based cancellation (default Ctrl+C behavior)
|
|
2013
1968
|
original_handler = signal.signal(
|
|
2014
1969
|
signal.SIGINT, keyboard_interrupt_handler
|
|
2015
1970
|
)
|
|
2016
1971
|
else:
|
|
2017
|
-
#
|
|
1972
|
+
# Use keyboard listener for agent cancellation
|
|
1973
|
+
# Set a graceful SIGINT handler that shows a hint
|
|
2018
1974
|
original_handler = signal.signal(signal.SIGINT, graceful_sigint_handler)
|
|
1975
|
+
# Spawn keyboard listener with the cancel agent callback
|
|
2019
1976
|
key_listener_stop_event = threading.Event()
|
|
2020
1977
|
_key_listener_thread = self._spawn_ctrl_x_key_listener(
|
|
2021
1978
|
key_listener_stop_event,
|
|
2022
|
-
on_escape=lambda: None,
|
|
1979
|
+
on_escape=lambda: None, # Ctrl+X handled by command_runner
|
|
2023
1980
|
on_cancel_agent=schedule_agent_cancel,
|
|
2024
1981
|
)
|
|
2025
1982
|
|
|
@@ -2044,17 +2001,8 @@ class BaseAgent(ABC):
|
|
|
2044
2001
|
# Stop keyboard listener if it was started
|
|
2045
2002
|
if key_listener_stop_event is not None:
|
|
2046
2003
|
key_listener_stop_event.set()
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
import ctypes
|
|
2052
|
-
|
|
2053
|
-
kernel32 = ctypes.windll.kernel32
|
|
2054
|
-
kernel32.SetConsoleCtrlHandler(_windows_ctrl_handler, False)
|
|
2055
|
-
except Exception:
|
|
2056
|
-
pass # Best effort cleanup
|
|
2057
|
-
|
|
2058
|
-
# Restore original signal handler (Unix)
|
|
2059
|
-
if original_handler is not None:
|
|
2004
|
+
# Restore original signal handler
|
|
2005
|
+
if (
|
|
2006
|
+
original_handler is not None
|
|
2007
|
+
): # Explicit None check - SIG_DFL can be 0/falsy!
|
|
2060
2008
|
signal.signal(signal.SIGINT, original_handler)
|
|
@@ -790,6 +790,5 @@ def main_entry():
|
|
|
790
790
|
DBOS.destroy()
|
|
791
791
|
return 0
|
|
792
792
|
finally:
|
|
793
|
-
# Reset terminal on
|
|
794
|
-
reset_windows_terminal_full() # Safe no-op on non-Windows
|
|
793
|
+
# Reset terminal on Unix-like systems (not Windows)
|
|
795
794
|
reset_unix_terminal()
|
|
@@ -46,6 +46,7 @@ def handle_show_command(command: str) -> bool:
|
|
|
46
46
|
get_use_dbos,
|
|
47
47
|
get_yolo_mode,
|
|
48
48
|
)
|
|
49
|
+
from code_puppy.keymap import get_cancel_agent_key, get_cancel_agent_display_name
|
|
49
50
|
from code_puppy.messaging import emit_info
|
|
50
51
|
|
|
51
52
|
puppy_name = get_puppy_name()
|
|
@@ -79,6 +80,7 @@ def handle_show_command(command: str) -> bool:
|
|
|
79
80
|
[bold]reasoning_effort:[/bold] [cyan]{get_openai_reasoning_effort()}[/cyan]
|
|
80
81
|
[bold]verbosity:[/bold] [cyan]{get_openai_verbosity()}[/cyan]
|
|
81
82
|
[bold]temperature:[/bold] [cyan]{effective_temperature if effective_temperature is not None else "(model default)"}[/cyan]{" (per-model)" if effective_temperature != global_temperature and effective_temperature is not None else ""}
|
|
83
|
+
[bold]cancel_agent_key:[/bold] [cyan]{get_cancel_agent_display_name()}[/cyan] (options: ctrl+c, ctrl+k, ctrl+q)
|
|
82
84
|
|
|
83
85
|
"""
|
|
84
86
|
emit_info(Text.from_markup(status_msg))
|
|
@@ -200,9 +202,13 @@ def handle_set_command(command: str) -> bool:
|
|
|
200
202
|
"\n[yellow]Session Management[/yellow]"
|
|
201
203
|
"\n [cyan]auto_save_session[/cyan] Auto-save chat after every response (true/false)"
|
|
202
204
|
)
|
|
205
|
+
keymap_help = (
|
|
206
|
+
"\n[yellow]Keyboard Shortcuts[/yellow]"
|
|
207
|
+
"\n [cyan]cancel_agent_key[/cyan] Key to cancel agent tasks (ctrl+c, ctrl+k, or ctrl+q)"
|
|
208
|
+
)
|
|
203
209
|
emit_warning(
|
|
204
210
|
Text.from_markup(
|
|
205
|
-
f"Usage: /set KEY=VALUE or /set KEY VALUE\nConfig keys: {', '.join(config_keys)}\n[dim]Note: compaction_strategy can be 'summarization' or 'truncation'[/dim]{session_help}"
|
|
211
|
+
f"Usage: /set KEY=VALUE or /set KEY VALUE\nConfig keys: {', '.join(config_keys)}\n[dim]Note: compaction_strategy can be 'summarization' or 'truncation'[/dim]{session_help}{keymap_help}"
|
|
206
212
|
)
|
|
207
213
|
)
|
|
208
214
|
return True
|
|
@@ -215,6 +221,23 @@ def handle_set_command(command: str) -> bool:
|
|
|
215
221
|
)
|
|
216
222
|
)
|
|
217
223
|
|
|
224
|
+
# Validate cancel_agent_key before setting
|
|
225
|
+
if key == "cancel_agent_key":
|
|
226
|
+
from code_puppy.keymap import VALID_CANCEL_KEYS
|
|
227
|
+
|
|
228
|
+
normalized_value = value.strip().lower()
|
|
229
|
+
if normalized_value not in VALID_CANCEL_KEYS:
|
|
230
|
+
emit_error(
|
|
231
|
+
f"Invalid cancel_agent_key '{value}'. Valid options: {', '.join(sorted(VALID_CANCEL_KEYS))}"
|
|
232
|
+
)
|
|
233
|
+
return True
|
|
234
|
+
value = normalized_value # Use normalized value
|
|
235
|
+
emit_info(
|
|
236
|
+
Text.from_markup(
|
|
237
|
+
"[yellow]⚠️ cancel_agent_key changed. Please restart Code Puppy for this change to take effect.[/yellow]"
|
|
238
|
+
)
|
|
239
|
+
)
|
|
240
|
+
|
|
218
241
|
set_config_value(key, value)
|
|
219
242
|
emit_success(f'Set {key} = "{value}" in puppy.cfg!')
|
|
220
243
|
|
|
@@ -86,15 +86,9 @@ def cancel_agent_uses_signal() -> bool:
|
|
|
86
86
|
"""Check if the cancel agent key uses SIGINT (Ctrl+C).
|
|
87
87
|
|
|
88
88
|
Returns:
|
|
89
|
-
True if the cancel key is ctrl+c
|
|
90
|
-
|
|
89
|
+
True if the cancel key is ctrl+c (uses SIGINT handler),
|
|
90
|
+
False if it uses keyboard listener approach.
|
|
91
91
|
"""
|
|
92
|
-
import sys
|
|
93
|
-
|
|
94
|
-
# On Windows, always use keyboard listener - SIGINT is unreliable
|
|
95
|
-
if sys.platform == "win32":
|
|
96
|
-
return False
|
|
97
|
-
|
|
98
92
|
return get_cancel_agent_key() == "ctrl+c"
|
|
99
93
|
|
|
100
94
|
|
|
@@ -192,11 +192,6 @@ def kill_all_running_shell_processes() -> int:
|
|
|
192
192
|
"""Kill all currently tracked running shell processes and stop reader threads.
|
|
193
193
|
|
|
194
194
|
Returns the number of processes signaled.
|
|
195
|
-
|
|
196
|
-
Implementation notes:
|
|
197
|
-
- Atomically snapshot and clear the registry to prevent race conditions
|
|
198
|
-
- Deduplicate by PID to ensure each process is killed at most once
|
|
199
|
-
- Let exceptions from _kill_process_group propagate (tests expect this)
|
|
200
195
|
"""
|
|
201
196
|
global _READER_STOP_EVENT
|
|
202
197
|
|
|
@@ -204,52 +199,30 @@ def kill_all_running_shell_processes() -> int:
|
|
|
204
199
|
if _READER_STOP_EVENT:
|
|
205
200
|
_READER_STOP_EVENT.set()
|
|
206
201
|
|
|
207
|
-
|
|
208
|
-
# This prevents other threads from seeing/processing the same processes
|
|
202
|
+
procs: list[subprocess.Popen]
|
|
209
203
|
with _RUNNING_PROCESSES_LOCK:
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
# Deduplicate by pid to ensure at-most-one kill per process
|
|
214
|
-
seen_pids: set = set()
|
|
215
|
-
killed_count = 0
|
|
216
|
-
|
|
217
|
-
for proc in procs_snapshot:
|
|
218
|
-
if proc is None:
|
|
219
|
-
continue
|
|
220
|
-
|
|
221
|
-
pid = getattr(proc, "pid", None)
|
|
222
|
-
key = pid if pid is not None else id(proc)
|
|
223
|
-
|
|
224
|
-
if key in seen_pids:
|
|
225
|
-
continue
|
|
226
|
-
seen_pids.add(key)
|
|
227
|
-
|
|
228
|
-
# Close pipes first to unblock readline()
|
|
204
|
+
procs = list(_RUNNING_PROCESSES)
|
|
205
|
+
count = 0
|
|
206
|
+
for p in procs:
|
|
229
207
|
try:
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
if proc.poll() is None:
|
|
241
|
-
# Let exceptions bubble up (tests expect this behavior)
|
|
242
|
-
_kill_process_group(proc)
|
|
243
|
-
killed_count += 1
|
|
244
|
-
|
|
245
|
-
# Track user-killed PIDs
|
|
246
|
-
if pid is not None:
|
|
247
|
-
try:
|
|
248
|
-
_USER_KILLED_PROCESSES.add(pid)
|
|
249
|
-
except Exception:
|
|
250
|
-
pass # Non-fatal bookkeeping
|
|
208
|
+
# Close pipes first to unblock readline()
|
|
209
|
+
try:
|
|
210
|
+
if p.stdout and not p.stdout.closed:
|
|
211
|
+
p.stdout.close()
|
|
212
|
+
if p.stderr and not p.stderr.closed:
|
|
213
|
+
p.stderr.close()
|
|
214
|
+
if p.stdin and not p.stdin.closed:
|
|
215
|
+
p.stdin.close()
|
|
216
|
+
except (OSError, ValueError):
|
|
217
|
+
pass
|
|
251
218
|
|
|
252
|
-
|
|
219
|
+
if p.poll() is None:
|
|
220
|
+
_kill_process_group(p)
|
|
221
|
+
count += 1
|
|
222
|
+
_USER_KILLED_PROCESSES.add(p.pid)
|
|
223
|
+
finally:
|
|
224
|
+
_unregister_process(p)
|
|
225
|
+
return count
|
|
253
226
|
|
|
254
227
|
|
|
255
228
|
def get_running_shell_process_count() -> int:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/load_context_completion.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/mcp/catalog_server_installer.py
RENAMED
|
File without changes
|
|
File without changes
|
{code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/mcp/custom_server_installer.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/model_picker_completion.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/command_line/prompt_toolkit_completion.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/plugins/chatgpt_oauth/register_callbacks.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/plugins/claude_code_oauth/register_callbacks.py
RENAMED
|
File without changes
|
{code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/plugins/claude_code_oauth/test_plugin.py
RENAMED
|
File without changes
|
|
File without changes
|
{code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/plugins/customizable_commands/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/plugins/example_custom_command/README.md
RENAMED
|
File without changes
|
|
File without changes
|
{code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/plugins/file_permission_handler/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/plugins/shell_safety/agent_shell_safety.py
RENAMED
|
File without changes
|
|
File without changes
|
{code_puppy-0.0.325 → code_puppy-0.0.327}/code_puppy/plugins/shell_safety/register_callbacks.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|