code-puppy 0.0.326__tar.gz → 0.0.328__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.326 → code_puppy-0.0.328}/PKG-INFO +30 -1
- {code_puppy-0.0.326 → code_puppy-0.0.328}/README.md +29 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/agents/base_agent.py +28 -2
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/command_line/config_commands.py +24 -1
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/tools/command_runner.py +89 -4
- {code_puppy-0.0.326 → code_puppy-0.0.328}/pyproject.toml +1 -1
- {code_puppy-0.0.326 → code_puppy-0.0.328}/.gitignore +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/LICENSE +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/__init__.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/__main__.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/agents/__init__.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/agents/agent_c_reviewer.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/agents/agent_code_puppy.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/agents/agent_code_reviewer.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/agents/agent_cpp_reviewer.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/agents/agent_creator_agent.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/agents/agent_golang_reviewer.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/agents/agent_javascript_reviewer.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/agents/agent_manager.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/agents/agent_planning.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/agents/agent_python_programmer.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/agents/agent_python_reviewer.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/agents/agent_qa_expert.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/agents/agent_qa_kitten.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/agents/agent_security_auditor.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/agents/agent_typescript_reviewer.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/agents/json_agent.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/agents/prompt_reviewer.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/callbacks.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/chatgpt_codex_client.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/claude_cache_client.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/cli_runner.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/command_line/__init__.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/command_line/add_model_menu.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/command_line/attachments.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/command_line/autosave_menu.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/command_line/colors_menu.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/command_line/command_handler.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/command_line/command_registry.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/command_line/core_commands.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/command_line/diff_menu.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/command_line/file_path_completion.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/command_line/load_context_completion.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/command_line/mcp/__init__.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/command_line/mcp/add_command.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/command_line/mcp/base.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/command_line/mcp/catalog_server_installer.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/command_line/mcp/custom_server_form.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/command_line/mcp/custom_server_installer.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/command_line/mcp/edit_command.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/command_line/mcp/handler.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/command_line/mcp/help_command.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/command_line/mcp/install_command.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/command_line/mcp/install_menu.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/command_line/mcp/list_command.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/command_line/mcp/logs_command.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/command_line/mcp/remove_command.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/command_line/mcp/restart_command.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/command_line/mcp/search_command.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/command_line/mcp/start_all_command.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/command_line/mcp/start_command.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/command_line/mcp/status_command.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/command_line/mcp/stop_all_command.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/command_line/mcp/stop_command.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/command_line/mcp/test_command.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/command_line/mcp/utils.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/command_line/mcp/wizard_utils.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/command_line/mcp_completion.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/command_line/model_picker_completion.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/command_line/model_settings_menu.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/command_line/motd.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/command_line/pin_command_completion.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/command_line/prompt_toolkit_completion.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/command_line/session_commands.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/command_line/utils.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/config.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/error_logging.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/gemini_code_assist.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/http_utils.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/keymap.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/main.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/mcp_/__init__.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/mcp_/async_lifecycle.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/mcp_/blocking_startup.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/mcp_/captured_stdio_server.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/mcp_/circuit_breaker.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/mcp_/config_wizard.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/mcp_/dashboard.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/mcp_/error_isolation.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/mcp_/examples/retry_example.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/mcp_/health_monitor.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/mcp_/managed_server.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/mcp_/manager.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/mcp_/mcp_logs.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/mcp_/registry.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/mcp_/retry_manager.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/mcp_/server_registry_catalog.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/mcp_/status_tracker.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/mcp_/system_tools.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/messaging/__init__.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/messaging/bus.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/messaging/commands.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/messaging/markdown_patches.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/messaging/message_queue.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/messaging/messages.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/messaging/queue_console.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/messaging/renderers.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/messaging/rich_renderer.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/messaging/spinner/__init__.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/messaging/spinner/console_spinner.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/messaging/spinner/spinner_base.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/model_factory.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/model_utils.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/models.json +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/models_dev_api.json +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/models_dev_parser.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/plugins/__init__.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/plugins/chatgpt_oauth/__init__.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/plugins/chatgpt_oauth/config.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/plugins/chatgpt_oauth/oauth_flow.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/plugins/chatgpt_oauth/register_callbacks.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/plugins/chatgpt_oauth/test_plugin.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/plugins/chatgpt_oauth/utils.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/plugins/claude_code_oauth/README.md +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/plugins/claude_code_oauth/SETUP.md +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/plugins/claude_code_oauth/__init__.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/plugins/claude_code_oauth/config.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/plugins/claude_code_oauth/register_callbacks.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/plugins/claude_code_oauth/test_plugin.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/plugins/claude_code_oauth/utils.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/plugins/customizable_commands/__init__.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/plugins/customizable_commands/register_callbacks.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/plugins/example_custom_command/README.md +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/plugins/example_custom_command/register_callbacks.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/plugins/file_permission_handler/__init__.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/plugins/file_permission_handler/register_callbacks.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/plugins/oauth_puppy_html.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/plugins/shell_safety/__init__.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/plugins/shell_safety/agent_shell_safety.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/plugins/shell_safety/command_cache.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/plugins/shell_safety/register_callbacks.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/prompts/codex_system_prompt.md +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/pydantic_patches.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/reopenable_async_client.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/round_robin_model.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/session_storage.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/status_display.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/summarization_agent.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/terminal_utils.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/tools/__init__.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/tools/agent_tools.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/tools/browser/__init__.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/tools/browser/browser_control.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/tools/browser/browser_interactions.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/tools/browser/browser_locators.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/tools/browser/browser_navigation.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/tools/browser/browser_screenshot.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/tools/browser/browser_scripts.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/tools/browser/browser_workflows.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/tools/browser/camoufox_manager.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/tools/browser/vqa_agent.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/tools/common.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/tools/file_modifications.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/tools/file_operations.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/tools/tools_content.py +0 -0
- {code_puppy-0.0.326 → code_puppy-0.0.328}/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.328
|
|
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)
|
|
@@ -75,6 +75,8 @@ from code_puppy.model_factory import ModelFactory, make_model_settings
|
|
|
75
75
|
from code_puppy.summarization_agent import run_summarization_sync
|
|
76
76
|
from code_puppy.tools.agent_tools import _active_subagent_tasks
|
|
77
77
|
from code_puppy.tools.command_runner import (
|
|
78
|
+
_add_windows_ctrl_handler,
|
|
79
|
+
_remove_windows_ctrl_handler,
|
|
78
80
|
is_awaiting_user_input,
|
|
79
81
|
)
|
|
80
82
|
|
|
@@ -1951,8 +1953,6 @@ class BaseAgent(ABC):
|
|
|
1951
1953
|
def graceful_sigint_handler(_sig, _frame):
|
|
1952
1954
|
# When using keyboard-based cancel, SIGINT should be a no-op
|
|
1953
1955
|
# (just show a hint to user about the configured cancel key)
|
|
1954
|
-
import sys
|
|
1955
|
-
|
|
1956
1956
|
from code_puppy.keymap import get_cancel_agent_display_name
|
|
1957
1957
|
|
|
1958
1958
|
cancel_key = get_cancel_agent_display_name()
|
|
@@ -1961,6 +1961,12 @@ class BaseAgent(ABC):
|
|
|
1961
1961
|
original_handler = None
|
|
1962
1962
|
key_listener_stop_event = None
|
|
1963
1963
|
_key_listener_thread = None
|
|
1964
|
+
windows_ctrl_handler = None
|
|
1965
|
+
|
|
1966
|
+
# Check if we're on Windows
|
|
1967
|
+
import sys
|
|
1968
|
+
|
|
1969
|
+
is_windows = sys.platform.startswith("win")
|
|
1964
1970
|
|
|
1965
1971
|
try:
|
|
1966
1972
|
if cancel_agent_uses_signal():
|
|
@@ -1968,10 +1974,27 @@ class BaseAgent(ABC):
|
|
|
1968
1974
|
original_handler = signal.signal(
|
|
1969
1975
|
signal.SIGINT, keyboard_interrupt_handler
|
|
1970
1976
|
)
|
|
1977
|
+
# On Windows, also use SetConsoleCtrlHandler for reliable Ctrl+C with uvx
|
|
1978
|
+
if is_windows:
|
|
1979
|
+
windows_ctrl_handler = _add_windows_ctrl_handler(
|
|
1980
|
+
schedule_agent_cancel
|
|
1981
|
+
)
|
|
1971
1982
|
else:
|
|
1972
1983
|
# Use keyboard listener for agent cancellation
|
|
1973
1984
|
# Set a graceful SIGINT handler that shows a hint
|
|
1974
1985
|
original_handler = signal.signal(signal.SIGINT, graceful_sigint_handler)
|
|
1986
|
+
# On Windows, SetConsoleCtrlHandler should also show the hint
|
|
1987
|
+
if is_windows:
|
|
1988
|
+
|
|
1989
|
+
def graceful_ctrl_handler():
|
|
1990
|
+
from code_puppy.keymap import get_cancel_agent_display_name
|
|
1991
|
+
|
|
1992
|
+
cancel_key = get_cancel_agent_display_name()
|
|
1993
|
+
emit_info(f"Use {cancel_key} to cancel the agent task.")
|
|
1994
|
+
|
|
1995
|
+
windows_ctrl_handler = _add_windows_ctrl_handler(
|
|
1996
|
+
graceful_ctrl_handler
|
|
1997
|
+
)
|
|
1975
1998
|
# Spawn keyboard listener with the cancel agent callback
|
|
1976
1999
|
key_listener_stop_event = threading.Event()
|
|
1977
2000
|
_key_listener_thread = self._spawn_ctrl_x_key_listener(
|
|
@@ -2001,6 +2024,9 @@ class BaseAgent(ABC):
|
|
|
2001
2024
|
# Stop keyboard listener if it was started
|
|
2002
2025
|
if key_listener_stop_event is not None:
|
|
2003
2026
|
key_listener_stop_event.set()
|
|
2027
|
+
# Remove Windows console handler
|
|
2028
|
+
if windows_ctrl_handler is not None:
|
|
2029
|
+
_remove_windows_ctrl_handler(windows_ctrl_handler)
|
|
2004
2030
|
# Restore original signal handler
|
|
2005
2031
|
if (
|
|
2006
2032
|
original_handler is not None
|
|
@@ -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
|
|
|
@@ -44,9 +44,70 @@ def _truncate_line(line: str) -> str:
|
|
|
44
44
|
if sys.platform.startswith("win"):
|
|
45
45
|
import msvcrt
|
|
46
46
|
|
|
47
|
-
# Load kernel32 for PeekNamedPipe
|
|
47
|
+
# Load kernel32 for PeekNamedPipe and SetConsoleCtrlHandler
|
|
48
48
|
_kernel32 = ctypes.windll.kernel32
|
|
49
49
|
|
|
50
|
+
# SetConsoleCtrlHandler types for Ctrl+C handling on Windows
|
|
51
|
+
# This is more reliable than signal.SIGINT when running under uvx
|
|
52
|
+
_CTRL_C_EVENT = 0
|
|
53
|
+
_CTRL_BREAK_EVENT = 1
|
|
54
|
+
_HANDLER_ROUTINE = ctypes.WINFUNCTYPE(ctypes.c_int, ctypes.c_ulong)
|
|
55
|
+
|
|
56
|
+
# Track registered handlers to prevent garbage collection
|
|
57
|
+
_registered_console_handlers: list = []
|
|
58
|
+
|
|
59
|
+
def _add_windows_ctrl_handler(callback: Callable[[], None]) -> Optional[Callable]:
|
|
60
|
+
"""Register a Windows console control handler for Ctrl+C/Ctrl+Break.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
callback: Function to call when Ctrl+C or Ctrl+Break is pressed.
|
|
64
|
+
Should take no arguments.
|
|
65
|
+
|
|
66
|
+
Returns:
|
|
67
|
+
The wrapped handler function (needed for removal), or None if failed.
|
|
68
|
+
"""
|
|
69
|
+
|
|
70
|
+
def handler(ctrl_type: int) -> int:
|
|
71
|
+
if ctrl_type in (_CTRL_C_EVENT, _CTRL_BREAK_EVENT):
|
|
72
|
+
try:
|
|
73
|
+
callback()
|
|
74
|
+
except Exception:
|
|
75
|
+
pass
|
|
76
|
+
return 1 # TRUE = we handled it, don't pass to next handler
|
|
77
|
+
return 0 # FALSE = let next handler deal with it
|
|
78
|
+
|
|
79
|
+
# Wrap in WINFUNCTYPE to make it callable from C
|
|
80
|
+
wrapped = _HANDLER_ROUTINE(handler)
|
|
81
|
+
# Keep reference to prevent GC
|
|
82
|
+
_registered_console_handlers.append(wrapped)
|
|
83
|
+
|
|
84
|
+
try:
|
|
85
|
+
if _kernel32.SetConsoleCtrlHandler(wrapped, True):
|
|
86
|
+
return wrapped
|
|
87
|
+
except Exception:
|
|
88
|
+
pass
|
|
89
|
+
return None
|
|
90
|
+
|
|
91
|
+
def _remove_windows_ctrl_handler(handler: Callable) -> bool:
|
|
92
|
+
"""Remove a previously registered Windows console control handler.
|
|
93
|
+
|
|
94
|
+
Args:
|
|
95
|
+
handler: The handler returned by _add_windows_ctrl_handler.
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
True if successfully removed, False otherwise.
|
|
99
|
+
"""
|
|
100
|
+
if handler is None:
|
|
101
|
+
return False
|
|
102
|
+
try:
|
|
103
|
+
result = _kernel32.SetConsoleCtrlHandler(handler, False)
|
|
104
|
+
# Clean up our reference
|
|
105
|
+
if handler in _registered_console_handlers:
|
|
106
|
+
_registered_console_handlers.remove(handler)
|
|
107
|
+
return bool(result)
|
|
108
|
+
except Exception:
|
|
109
|
+
return False
|
|
110
|
+
|
|
50
111
|
def _win32_pipe_has_data(pipe) -> bool:
|
|
51
112
|
"""Check if a Windows pipe has data available without blocking.
|
|
52
113
|
|
|
@@ -87,8 +148,15 @@ if sys.platform.startswith("win"):
|
|
|
87
148
|
except (ValueError, OSError, ctypes.ArgumentError):
|
|
88
149
|
# Handle closed, invalid, or other errors
|
|
89
150
|
return False
|
|
151
|
+
|
|
90
152
|
else:
|
|
91
|
-
#
|
|
153
|
+
# Non-Windows: provide no-op stubs
|
|
154
|
+
def _add_windows_ctrl_handler(callback: Callable[[], None]) -> Optional[Callable]:
|
|
155
|
+
return None
|
|
156
|
+
|
|
157
|
+
def _remove_windows_ctrl_handler(handler: Callable) -> bool:
|
|
158
|
+
return False
|
|
159
|
+
|
|
92
160
|
def _win32_pipe_has_data(pipe) -> bool:
|
|
93
161
|
return False
|
|
94
162
|
|
|
@@ -106,6 +174,7 @@ _USER_KILLED_PROCESSES = set()
|
|
|
106
174
|
_SHELL_CTRL_X_STOP_EVENT: Optional[threading.Event] = None
|
|
107
175
|
_SHELL_CTRL_X_THREAD: Optional[threading.Thread] = None
|
|
108
176
|
_ORIGINAL_SIGINT_HANDLER = None
|
|
177
|
+
_WINDOWS_CTRL_HANDLER = None # For SetConsoleCtrlHandler on Windows
|
|
109
178
|
|
|
110
179
|
# Stop event to signal reader threads to terminate
|
|
111
180
|
_READER_STOP_EVENT: Optional[threading.Event] = None
|
|
@@ -435,8 +504,10 @@ def _shell_command_keyboard_context():
|
|
|
435
504
|
1. Disables the agent's Ctrl-C handler (so it doesn't cancel the agent)
|
|
436
505
|
2. Enables a Ctrl-X listener to kill the running shell process
|
|
437
506
|
3. Restores the original Ctrl-C handler when done
|
|
507
|
+
4. On Windows, uses SetConsoleCtrlHandler for reliable Ctrl+C with uvx
|
|
438
508
|
"""
|
|
439
509
|
global _SHELL_CTRL_X_STOP_EVENT, _SHELL_CTRL_X_THREAD, _ORIGINAL_SIGINT_HANDLER
|
|
510
|
+
global _WINDOWS_CTRL_HANDLER
|
|
440
511
|
|
|
441
512
|
# Handler for Ctrl-X: kill all running shell processes
|
|
442
513
|
def handle_ctrl_x_press() -> None:
|
|
@@ -444,11 +515,15 @@ def _shell_command_keyboard_context():
|
|
|
444
515
|
kill_all_running_shell_processes()
|
|
445
516
|
|
|
446
517
|
# Handler for Ctrl-C during shell execution: just kill the shell process, don't cancel agent
|
|
447
|
-
def
|
|
518
|
+
def shell_ctrl_c_callback():
|
|
448
519
|
"""During shell execution, Ctrl-C kills the shell but doesn't cancel the agent."""
|
|
449
520
|
emit_warning("\n🛑 Ctrl-C detected! Interrupting shell command...")
|
|
450
521
|
kill_all_running_shell_processes()
|
|
451
522
|
|
|
523
|
+
def shell_sigint_handler(_sig, _frame):
|
|
524
|
+
"""Signal handler wrapper for SIGINT."""
|
|
525
|
+
shell_ctrl_c_callback()
|
|
526
|
+
|
|
452
527
|
# Set up Ctrl-X listener
|
|
453
528
|
_SHELL_CTRL_X_STOP_EVENT = threading.Event()
|
|
454
529
|
_SHELL_CTRL_X_THREAD = _spawn_ctrl_x_key_listener(
|
|
@@ -456,7 +531,12 @@ def _shell_command_keyboard_context():
|
|
|
456
531
|
handle_ctrl_x_press,
|
|
457
532
|
)
|
|
458
533
|
|
|
459
|
-
#
|
|
534
|
+
# On Windows, use SetConsoleCtrlHandler for reliable Ctrl+C handling
|
|
535
|
+
# This works even when running under uvx where SIGINT doesn't propagate properly
|
|
536
|
+
if sys.platform.startswith("win"):
|
|
537
|
+
_WINDOWS_CTRL_HANDLER = _add_windows_ctrl_handler(shell_ctrl_c_callback)
|
|
538
|
+
|
|
539
|
+
# Also set SIGINT handler (works on POSIX, may work on some Windows setups)
|
|
460
540
|
try:
|
|
461
541
|
_ORIGINAL_SIGINT_HANDLER = signal.signal(signal.SIGINT, shell_sigint_handler)
|
|
462
542
|
except (ValueError, OSError):
|
|
@@ -476,6 +556,10 @@ def _shell_command_keyboard_context():
|
|
|
476
556
|
except Exception:
|
|
477
557
|
pass
|
|
478
558
|
|
|
559
|
+
# Remove Windows console handler
|
|
560
|
+
if _WINDOWS_CTRL_HANDLER is not None:
|
|
561
|
+
_remove_windows_ctrl_handler(_WINDOWS_CTRL_HANDLER)
|
|
562
|
+
|
|
479
563
|
# Restore original SIGINT handler
|
|
480
564
|
if _ORIGINAL_SIGINT_HANDLER is not None:
|
|
481
565
|
try:
|
|
@@ -487,6 +571,7 @@ def _shell_command_keyboard_context():
|
|
|
487
571
|
_SHELL_CTRL_X_STOP_EVENT = None
|
|
488
572
|
_SHELL_CTRL_X_THREAD = None
|
|
489
573
|
_ORIGINAL_SIGINT_HANDLER = None
|
|
574
|
+
_WINDOWS_CTRL_HANDLER = None
|
|
490
575
|
|
|
491
576
|
|
|
492
577
|
def run_shell_command_streaming(
|
|
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.326 → code_puppy-0.0.328}/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.326 → code_puppy-0.0.328}/code_puppy/command_line/mcp/catalog_server_installer.py
RENAMED
|
File without changes
|
|
File without changes
|
{code_puppy-0.0.326 → code_puppy-0.0.328}/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.326 → code_puppy-0.0.328}/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.326 → code_puppy-0.0.328}/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
|
|
File without changes
|
{code_puppy-0.0.326 → code_puppy-0.0.328}/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.326 → code_puppy-0.0.328}/code_puppy/plugins/claude_code_oauth/register_callbacks.py
RENAMED
|
File without changes
|
{code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/plugins/claude_code_oauth/test_plugin.py
RENAMED
|
File without changes
|
|
File without changes
|
{code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/plugins/customizable_commands/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{code_puppy-0.0.326 → code_puppy-0.0.328}/code_puppy/plugins/example_custom_command/README.md
RENAMED
|
File without changes
|
|
File without changes
|
{code_puppy-0.0.326 → code_puppy-0.0.328}/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.326 → code_puppy-0.0.328}/code_puppy/plugins/shell_safety/agent_shell_safety.py
RENAMED
|
File without changes
|
|
File without changes
|
{code_puppy-0.0.326 → code_puppy-0.0.328}/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
|