code-puppy 0.0.322__tar.gz → 0.0.324__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.322 → code_puppy-0.0.324}/PKG-INFO +1 -1
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/agents/base_agent.py +64 -11
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/cli_runner.py +2 -1
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/keymap.py +8 -2
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/models.json +2 -2
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/tools/command_runner.py +48 -21
- {code_puppy-0.0.322 → code_puppy-0.0.324}/pyproject.toml +1 -1
- {code_puppy-0.0.322 → code_puppy-0.0.324}/.gitignore +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/LICENSE +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/README.md +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/__init__.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/__main__.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/agents/__init__.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/agents/agent_c_reviewer.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/agents/agent_code_puppy.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/agents/agent_code_reviewer.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/agents/agent_cpp_reviewer.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/agents/agent_creator_agent.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/agents/agent_golang_reviewer.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/agents/agent_javascript_reviewer.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/agents/agent_manager.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/agents/agent_planning.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/agents/agent_python_programmer.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/agents/agent_python_reviewer.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/agents/agent_qa_expert.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/agents/agent_qa_kitten.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/agents/agent_security_auditor.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/agents/agent_typescript_reviewer.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/agents/json_agent.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/agents/prompt_reviewer.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/callbacks.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/chatgpt_codex_client.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/claude_cache_client.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/command_line/__init__.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/command_line/add_model_menu.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/command_line/attachments.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/command_line/autosave_menu.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/command_line/colors_menu.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/command_line/command_handler.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/command_line/command_registry.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/command_line/config_commands.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/command_line/core_commands.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/command_line/diff_menu.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/command_line/file_path_completion.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/command_line/load_context_completion.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/command_line/mcp/__init__.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/command_line/mcp/add_command.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/command_line/mcp/base.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/command_line/mcp/catalog_server_installer.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/command_line/mcp/custom_server_form.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/command_line/mcp/custom_server_installer.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/command_line/mcp/edit_command.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/command_line/mcp/handler.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/command_line/mcp/help_command.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/command_line/mcp/install_command.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/command_line/mcp/install_menu.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/command_line/mcp/list_command.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/command_line/mcp/logs_command.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/command_line/mcp/remove_command.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/command_line/mcp/restart_command.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/command_line/mcp/search_command.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/command_line/mcp/start_all_command.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/command_line/mcp/start_command.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/command_line/mcp/status_command.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/command_line/mcp/stop_all_command.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/command_line/mcp/stop_command.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/command_line/mcp/test_command.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/command_line/mcp/utils.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/command_line/mcp/wizard_utils.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/command_line/mcp_completion.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/command_line/model_picker_completion.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/command_line/model_settings_menu.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/command_line/motd.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/command_line/pin_command_completion.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/command_line/prompt_toolkit_completion.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/command_line/session_commands.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/command_line/utils.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/config.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/error_logging.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/gemini_code_assist.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/http_utils.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/main.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/mcp_/__init__.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/mcp_/async_lifecycle.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/mcp_/blocking_startup.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/mcp_/captured_stdio_server.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/mcp_/circuit_breaker.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/mcp_/config_wizard.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/mcp_/dashboard.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/mcp_/error_isolation.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/mcp_/examples/retry_example.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/mcp_/health_monitor.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/mcp_/managed_server.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/mcp_/manager.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/mcp_/mcp_logs.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/mcp_/registry.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/mcp_/retry_manager.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/mcp_/server_registry_catalog.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/mcp_/status_tracker.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/mcp_/system_tools.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/messaging/__init__.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/messaging/bus.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/messaging/commands.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/messaging/markdown_patches.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/messaging/message_queue.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/messaging/messages.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/messaging/queue_console.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/messaging/renderers.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/messaging/rich_renderer.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/messaging/spinner/__init__.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/messaging/spinner/console_spinner.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/messaging/spinner/spinner_base.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/model_factory.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/model_utils.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/models_dev_api.json +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/models_dev_parser.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/plugins/__init__.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/plugins/chatgpt_oauth/__init__.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/plugins/chatgpt_oauth/config.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/plugins/chatgpt_oauth/oauth_flow.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/plugins/chatgpt_oauth/register_callbacks.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/plugins/chatgpt_oauth/test_plugin.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/plugins/chatgpt_oauth/utils.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/plugins/claude_code_oauth/README.md +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/plugins/claude_code_oauth/SETUP.md +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/plugins/claude_code_oauth/__init__.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/plugins/claude_code_oauth/config.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/plugins/claude_code_oauth/register_callbacks.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/plugins/claude_code_oauth/test_plugin.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/plugins/claude_code_oauth/utils.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/plugins/customizable_commands/__init__.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/plugins/customizable_commands/register_callbacks.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/plugins/example_custom_command/README.md +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/plugins/example_custom_command/register_callbacks.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/plugins/file_permission_handler/__init__.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/plugins/file_permission_handler/register_callbacks.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/plugins/oauth_puppy_html.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/plugins/shell_safety/__init__.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/plugins/shell_safety/agent_shell_safety.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/plugins/shell_safety/command_cache.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/plugins/shell_safety/register_callbacks.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/prompts/codex_system_prompt.md +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/pydantic_patches.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/reopenable_async_client.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/round_robin_model.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/session_storage.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/status_display.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/summarization_agent.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/terminal_utils.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/tools/__init__.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/tools/agent_tools.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/tools/browser/__init__.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/tools/browser/browser_control.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/tools/browser/browser_interactions.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/tools/browser/browser_locators.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/tools/browser/browser_navigation.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/tools/browser/browser_screenshot.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/tools/browser/browser_scripts.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/tools/browser/browser_workflows.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/tools/browser/camoufox_manager.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/tools/browser/vqa_agent.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/tools/common.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/tools/file_modifications.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/tools/file_operations.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/tools/tools_content.py +0 -0
- {code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/version_checker.py +0 -0
|
@@ -4,6 +4,7 @@ import asyncio
|
|
|
4
4
|
import json
|
|
5
5
|
import math
|
|
6
6
|
import signal
|
|
7
|
+
import sys
|
|
7
8
|
import threading
|
|
8
9
|
import uuid
|
|
9
10
|
from abc import ABC, abstractmethod
|
|
@@ -1910,29 +1911,72 @@ class BaseAgent(ABC):
|
|
|
1910
1911
|
# When using keyboard-based cancel, SIGINT should be a no-op
|
|
1911
1912
|
# (just show a hint to user about the configured cancel key)
|
|
1912
1913
|
from code_puppy.keymap import get_cancel_agent_display_name
|
|
1914
|
+
import sys
|
|
1913
1915
|
|
|
1914
1916
|
cancel_key = get_cancel_agent_display_name()
|
|
1915
|
-
|
|
1917
|
+
if sys.platform == "win32":
|
|
1918
|
+
# On Windows, we use keyboard listener, so SIGINT might still fire
|
|
1919
|
+
# but we handle cancellation via the key listener
|
|
1920
|
+
pass # Silent on Windows - the key listener handles it
|
|
1921
|
+
else:
|
|
1922
|
+
emit_info(f"Use {cancel_key} to cancel the agent task.")
|
|
1916
1923
|
|
|
1917
1924
|
original_handler = None
|
|
1918
1925
|
key_listener_stop_event = None
|
|
1919
1926
|
_key_listener_thread = None
|
|
1927
|
+
_windows_ctrl_handler = None # Store reference to prevent garbage collection
|
|
1920
1928
|
|
|
1921
1929
|
try:
|
|
1922
|
-
if
|
|
1923
|
-
# Use
|
|
1930
|
+
if sys.platform == "win32":
|
|
1931
|
+
# Windows: Use SetConsoleCtrlHandler for reliable Ctrl+C handling
|
|
1932
|
+
import ctypes
|
|
1933
|
+
|
|
1934
|
+
# Define the handler function type
|
|
1935
|
+
HANDLER_ROUTINE = ctypes.WINFUNCTYPE(ctypes.c_bool, ctypes.c_ulong)
|
|
1936
|
+
|
|
1937
|
+
def windows_ctrl_handler(ctrl_type):
|
|
1938
|
+
"""Handle Windows console control events."""
|
|
1939
|
+
CTRL_C_EVENT = 0
|
|
1940
|
+
CTRL_BREAK_EVENT = 1
|
|
1941
|
+
|
|
1942
|
+
if ctrl_type in (CTRL_C_EVENT, CTRL_BREAK_EVENT):
|
|
1943
|
+
# Check if we're awaiting user input
|
|
1944
|
+
if is_awaiting_user_input():
|
|
1945
|
+
return False # Let default handler run
|
|
1946
|
+
|
|
1947
|
+
# Schedule agent cancellation
|
|
1948
|
+
schedule_agent_cancel()
|
|
1949
|
+
return True # We handled it, don't terminate
|
|
1950
|
+
|
|
1951
|
+
return False # Let other handlers process it
|
|
1952
|
+
|
|
1953
|
+
# Create the callback - must keep reference alive!
|
|
1954
|
+
_windows_ctrl_handler = HANDLER_ROUTINE(windows_ctrl_handler)
|
|
1955
|
+
|
|
1956
|
+
# Register the handler
|
|
1957
|
+
kernel32 = ctypes.windll.kernel32
|
|
1958
|
+
if not kernel32.SetConsoleCtrlHandler(_windows_ctrl_handler, True):
|
|
1959
|
+
emit_warning("Failed to set Windows Ctrl+C handler")
|
|
1960
|
+
|
|
1961
|
+
# Also spawn keyboard listener for Ctrl+X (shell cancel) and other keys
|
|
1962
|
+
key_listener_stop_event = threading.Event()
|
|
1963
|
+
_key_listener_thread = self._spawn_ctrl_x_key_listener(
|
|
1964
|
+
key_listener_stop_event,
|
|
1965
|
+
on_escape=lambda: None, # Ctrl+X handled by command_runner
|
|
1966
|
+
on_cancel_agent=None, # Ctrl+C handled by SetConsoleCtrlHandler above
|
|
1967
|
+
)
|
|
1968
|
+
elif cancel_agent_uses_signal():
|
|
1969
|
+
# Unix with Ctrl+C: Use SIGINT-based cancellation
|
|
1924
1970
|
original_handler = signal.signal(
|
|
1925
1971
|
signal.SIGINT, keyboard_interrupt_handler
|
|
1926
1972
|
)
|
|
1927
1973
|
else:
|
|
1928
|
-
# Use keyboard listener
|
|
1929
|
-
# Set a graceful SIGINT handler that shows a hint
|
|
1974
|
+
# Unix with different cancel key: Use keyboard listener
|
|
1930
1975
|
original_handler = signal.signal(signal.SIGINT, graceful_sigint_handler)
|
|
1931
|
-
# Spawn keyboard listener with the cancel agent callback
|
|
1932
1976
|
key_listener_stop_event = threading.Event()
|
|
1933
1977
|
_key_listener_thread = self._spawn_ctrl_x_key_listener(
|
|
1934
1978
|
key_listener_stop_event,
|
|
1935
|
-
on_escape=lambda: None,
|
|
1979
|
+
on_escape=lambda: None,
|
|
1936
1980
|
on_cancel_agent=schedule_agent_cancel,
|
|
1937
1981
|
)
|
|
1938
1982
|
|
|
@@ -1957,8 +2001,17 @@ class BaseAgent(ABC):
|
|
|
1957
2001
|
# Stop keyboard listener if it was started
|
|
1958
2002
|
if key_listener_stop_event is not None:
|
|
1959
2003
|
key_listener_stop_event.set()
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
2004
|
+
|
|
2005
|
+
# Unregister Windows Ctrl handler
|
|
2006
|
+
if sys.platform == "win32" and _windows_ctrl_handler is not None:
|
|
2007
|
+
try:
|
|
2008
|
+
import ctypes
|
|
2009
|
+
|
|
2010
|
+
kernel32 = ctypes.windll.kernel32
|
|
2011
|
+
kernel32.SetConsoleCtrlHandler(_windows_ctrl_handler, False)
|
|
2012
|
+
except Exception:
|
|
2013
|
+
pass # Best effort cleanup
|
|
2014
|
+
|
|
2015
|
+
# Restore original signal handler (Unix)
|
|
2016
|
+
if original_handler is not None:
|
|
1964
2017
|
signal.signal(signal.SIGINT, original_handler)
|
|
@@ -790,5 +790,6 @@ def main_entry():
|
|
|
790
790
|
DBOS.destroy()
|
|
791
791
|
return 0
|
|
792
792
|
finally:
|
|
793
|
-
# Reset terminal on
|
|
793
|
+
# Reset terminal on all platforms for clean state
|
|
794
|
+
reset_windows_terminal_full() # Safe no-op on non-Windows
|
|
794
795
|
reset_unix_terminal()
|
|
@@ -86,9 +86,15 @@ 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
|
-
False if it uses keyboard listener approach.
|
|
89
|
+
True if the cancel key is ctrl+c AND we're not on Windows
|
|
90
|
+
(uses SIGINT handler), 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
|
+
|
|
92
98
|
return get_cancel_agent_key() == "ctrl+c"
|
|
93
99
|
|
|
94
100
|
|
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
"context_length": 200000,
|
|
10
10
|
"supported_settings": ["temperature", "seed"]
|
|
11
11
|
},
|
|
12
|
-
"synthetic-MiniMax-M2": {
|
|
12
|
+
"synthetic-MiniMax-M2.1": {
|
|
13
13
|
"type": "custom_openai",
|
|
14
|
-
"name": "hf:MiniMaxAI/MiniMax-M2",
|
|
14
|
+
"name": "hf:MiniMaxAI/MiniMax-M2.1",
|
|
15
15
|
"custom_endpoint": {
|
|
16
16
|
"url": "https://api.synthetic.new/openai/v1/",
|
|
17
17
|
"api_key": "$SYN_API_KEY"
|
|
@@ -192,6 +192,11 @@ 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)
|
|
195
200
|
"""
|
|
196
201
|
global _READER_STOP_EVENT
|
|
197
202
|
|
|
@@ -199,30 +204,52 @@ def kill_all_running_shell_processes() -> int:
|
|
|
199
204
|
if _READER_STOP_EVENT:
|
|
200
205
|
_READER_STOP_EVENT.set()
|
|
201
206
|
|
|
202
|
-
|
|
207
|
+
# Atomically take snapshot and clear registry
|
|
208
|
+
# This prevents other threads from seeing/processing the same processes
|
|
203
209
|
with _RUNNING_PROCESSES_LOCK:
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
210
|
+
procs_snapshot = list(_RUNNING_PROCESSES)
|
|
211
|
+
_RUNNING_PROCESSES.clear()
|
|
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()
|
|
207
229
|
try:
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
230
|
+
if proc.stdout and not proc.stdout.closed:
|
|
231
|
+
proc.stdout.close()
|
|
232
|
+
if proc.stderr and not proc.stderr.closed:
|
|
233
|
+
proc.stderr.close()
|
|
234
|
+
if proc.stdin and not proc.stdin.closed:
|
|
235
|
+
proc.stdin.close()
|
|
236
|
+
except (OSError, ValueError):
|
|
237
|
+
pass
|
|
238
|
+
|
|
239
|
+
# Only attempt to kill processes that are still running
|
|
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
|
|
218
251
|
|
|
219
|
-
|
|
220
|
-
_kill_process_group(p)
|
|
221
|
-
count += 1
|
|
222
|
-
_USER_KILLED_PROCESSES.add(p.pid)
|
|
223
|
-
finally:
|
|
224
|
-
_unregister_process(p)
|
|
225
|
-
return count
|
|
252
|
+
return killed_count
|
|
226
253
|
|
|
227
254
|
|
|
228
255
|
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
|
|
File without changes
|
|
File without changes
|
{code_puppy-0.0.322 → code_puppy-0.0.324}/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.322 → code_puppy-0.0.324}/code_puppy/command_line/mcp/catalog_server_installer.py
RENAMED
|
File without changes
|
|
File without changes
|
{code_puppy-0.0.322 → code_puppy-0.0.324}/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.322 → code_puppy-0.0.324}/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.322 → code_puppy-0.0.324}/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
|
{code_puppy-0.0.322 → code_puppy-0.0.324}/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.322 → code_puppy-0.0.324}/code_puppy/plugins/claude_code_oauth/register_callbacks.py
RENAMED
|
File without changes
|
{code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/plugins/claude_code_oauth/test_plugin.py
RENAMED
|
File without changes
|
|
File without changes
|
{code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/plugins/customizable_commands/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{code_puppy-0.0.322 → code_puppy-0.0.324}/code_puppy/plugins/example_custom_command/README.md
RENAMED
|
File without changes
|
|
File without changes
|
{code_puppy-0.0.322 → code_puppy-0.0.324}/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.322 → code_puppy-0.0.324}/code_puppy/plugins/shell_safety/agent_shell_safety.py
RENAMED
|
File without changes
|
|
File without changes
|
{code_puppy-0.0.322 → code_puppy-0.0.324}/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
|