code-puppy 0.0.324__tar.gz → 0.0.326__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.324 → code_puppy-0.0.326}/PKG-INFO +1 -1
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/agents/base_agent.py +69 -78
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/cli_runner.py +1 -2
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/command_line/add_model_menu.py +11 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/keymap.py +2 -8
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/plugins/__init__.py +12 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/tools/command_runner.py +21 -48
- {code_puppy-0.0.324 → code_puppy-0.0.326}/pyproject.toml +1 -1
- {code_puppy-0.0.324 → code_puppy-0.0.326}/.gitignore +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/LICENSE +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/README.md +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/__init__.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/__main__.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/agents/__init__.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/agents/agent_c_reviewer.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/agents/agent_code_puppy.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/agents/agent_code_reviewer.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/agents/agent_cpp_reviewer.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/agents/agent_creator_agent.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/agents/agent_golang_reviewer.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/agents/agent_javascript_reviewer.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/agents/agent_manager.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/agents/agent_planning.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/agents/agent_python_programmer.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/agents/agent_python_reviewer.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/agents/agent_qa_expert.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/agents/agent_qa_kitten.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/agents/agent_security_auditor.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/agents/agent_typescript_reviewer.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/agents/json_agent.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/agents/prompt_reviewer.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/callbacks.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/chatgpt_codex_client.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/claude_cache_client.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/command_line/__init__.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/command_line/attachments.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/command_line/autosave_menu.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/command_line/colors_menu.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/command_line/command_handler.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/command_line/command_registry.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/command_line/config_commands.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/command_line/core_commands.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/command_line/diff_menu.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/command_line/file_path_completion.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/command_line/load_context_completion.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/command_line/mcp/__init__.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/command_line/mcp/add_command.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/command_line/mcp/base.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/command_line/mcp/catalog_server_installer.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/command_line/mcp/custom_server_form.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/command_line/mcp/custom_server_installer.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/command_line/mcp/edit_command.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/command_line/mcp/handler.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/command_line/mcp/help_command.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/command_line/mcp/install_command.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/command_line/mcp/install_menu.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/command_line/mcp/list_command.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/command_line/mcp/logs_command.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/command_line/mcp/remove_command.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/command_line/mcp/restart_command.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/command_line/mcp/search_command.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/command_line/mcp/start_all_command.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/command_line/mcp/start_command.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/command_line/mcp/status_command.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/command_line/mcp/stop_all_command.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/command_line/mcp/stop_command.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/command_line/mcp/test_command.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/command_line/mcp/utils.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/command_line/mcp/wizard_utils.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/command_line/mcp_completion.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/command_line/model_picker_completion.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/command_line/model_settings_menu.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/command_line/motd.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/command_line/pin_command_completion.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/command_line/prompt_toolkit_completion.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/command_line/session_commands.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/command_line/utils.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/config.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/error_logging.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/gemini_code_assist.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/http_utils.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/main.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/mcp_/__init__.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/mcp_/async_lifecycle.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/mcp_/blocking_startup.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/mcp_/captured_stdio_server.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/mcp_/circuit_breaker.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/mcp_/config_wizard.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/mcp_/dashboard.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/mcp_/error_isolation.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/mcp_/examples/retry_example.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/mcp_/health_monitor.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/mcp_/managed_server.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/mcp_/manager.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/mcp_/mcp_logs.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/mcp_/registry.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/mcp_/retry_manager.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/mcp_/server_registry_catalog.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/mcp_/status_tracker.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/mcp_/system_tools.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/messaging/__init__.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/messaging/bus.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/messaging/commands.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/messaging/markdown_patches.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/messaging/message_queue.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/messaging/messages.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/messaging/queue_console.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/messaging/renderers.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/messaging/rich_renderer.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/messaging/spinner/__init__.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/messaging/spinner/console_spinner.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/messaging/spinner/spinner_base.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/model_factory.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/model_utils.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/models.json +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/models_dev_api.json +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/models_dev_parser.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/plugins/chatgpt_oauth/__init__.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/plugins/chatgpt_oauth/config.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/plugins/chatgpt_oauth/oauth_flow.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/plugins/chatgpt_oauth/register_callbacks.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/plugins/chatgpt_oauth/test_plugin.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/plugins/chatgpt_oauth/utils.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/plugins/claude_code_oauth/README.md +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/plugins/claude_code_oauth/SETUP.md +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/plugins/claude_code_oauth/__init__.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/plugins/claude_code_oauth/config.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/plugins/claude_code_oauth/register_callbacks.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/plugins/claude_code_oauth/test_plugin.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/plugins/claude_code_oauth/utils.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/plugins/customizable_commands/__init__.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/plugins/customizable_commands/register_callbacks.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/plugins/example_custom_command/README.md +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/plugins/example_custom_command/register_callbacks.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/plugins/file_permission_handler/__init__.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/plugins/file_permission_handler/register_callbacks.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/plugins/oauth_puppy_html.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/plugins/shell_safety/__init__.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/plugins/shell_safety/agent_shell_safety.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/plugins/shell_safety/command_cache.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/plugins/shell_safety/register_callbacks.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/prompts/codex_system_prompt.md +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/pydantic_patches.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/reopenable_async_client.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/round_robin_model.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/session_storage.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/status_display.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/summarization_agent.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/terminal_utils.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/tools/__init__.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/tools/agent_tools.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/tools/browser/__init__.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/tools/browser/browser_control.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/tools/browser/browser_interactions.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/tools/browser/browser_locators.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/tools/browser/browser_navigation.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/tools/browser/browser_screenshot.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/tools/browser/browser_scripts.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/tools/browser/browser_workflows.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/tools/browser/camoufox_manager.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/tools/browser/vqa_agent.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/tools/common.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/tools/file_modifications.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/tools/file_operations.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/tools/tools_content.py +0 -0
- {code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/version_checker.py +0 -0
|
@@ -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
|
|
@@ -1340,15 +1339,19 @@ class BaseAgent(ABC):
|
|
|
1340
1339
|
) -> None:
|
|
1341
1340
|
"""Handle streaming events from the agent run.
|
|
1342
1341
|
|
|
1343
|
-
This method processes streaming events and emits TextPart
|
|
1344
|
-
content with styled banners as they stream in.
|
|
1342
|
+
This method processes streaming events and emits TextPart, ThinkingPart,
|
|
1343
|
+
and ToolCallPart content with styled banners/tokens as they stream in.
|
|
1345
1344
|
|
|
1346
1345
|
Args:
|
|
1347
1346
|
ctx: The run context.
|
|
1348
1347
|
events: Async iterable of streaming events (PartStartEvent, PartDeltaEvent, etc.).
|
|
1349
1348
|
"""
|
|
1350
1349
|
from pydantic_ai import PartDeltaEvent, PartStartEvent
|
|
1351
|
-
from pydantic_ai.messages import
|
|
1350
|
+
from pydantic_ai.messages import (
|
|
1351
|
+
TextPartDelta,
|
|
1352
|
+
ThinkingPartDelta,
|
|
1353
|
+
ToolCallPartDelta,
|
|
1354
|
+
)
|
|
1352
1355
|
from rich.console import Console
|
|
1353
1356
|
from rich.markdown import Markdown
|
|
1354
1357
|
from rich.markup import escape
|
|
@@ -1364,15 +1367,16 @@ class BaseAgent(ABC):
|
|
|
1364
1367
|
# Fallback if console not set (shouldn't happen in normal use)
|
|
1365
1368
|
console = Console()
|
|
1366
1369
|
|
|
1367
|
-
# Track which part indices we're currently streaming (for Text/Thinking parts)
|
|
1370
|
+
# Track which part indices we're currently streaming (for Text/Thinking/Tool parts)
|
|
1368
1371
|
streaming_parts: set[int] = set()
|
|
1369
1372
|
thinking_parts: set[int] = (
|
|
1370
1373
|
set()
|
|
1371
1374
|
) # Track which parts are thinking (for dim style)
|
|
1372
1375
|
text_parts: set[int] = set() # Track which parts are text
|
|
1376
|
+
tool_parts: set[int] = set() # Track which parts are tool calls
|
|
1373
1377
|
banner_printed: set[int] = set() # Track if banner was already printed
|
|
1374
1378
|
text_buffer: dict[int, list[str]] = {} # Buffer text for final markdown render
|
|
1375
|
-
token_count: dict[int, int] = {} # Track token count per text part
|
|
1379
|
+
token_count: dict[int, int] = {} # Track token count per text/tool part
|
|
1376
1380
|
did_stream_anything = False # Track if we streamed any content
|
|
1377
1381
|
|
|
1378
1382
|
def _print_thinking_banner() -> None:
|
|
@@ -1442,7 +1446,16 @@ class BaseAgent(ABC):
|
|
|
1442
1446
|
# Buffer initial content if present
|
|
1443
1447
|
if part.content and part.content.strip():
|
|
1444
1448
|
text_buffer[event.index].append(part.content)
|
|
1445
|
-
|
|
1449
|
+
# Use len(content) / 3 for token estimation (more accurate than chunk counting)
|
|
1450
|
+
token_count[event.index] += len(part.content) // 3
|
|
1451
|
+
elif isinstance(part, ToolCallPart):
|
|
1452
|
+
streaming_parts.add(event.index)
|
|
1453
|
+
tool_parts.add(event.index)
|
|
1454
|
+
token_count[event.index] = 0 # Initialize token counter
|
|
1455
|
+
# Track tool name for display
|
|
1456
|
+
banner_printed.add(
|
|
1457
|
+
event.index
|
|
1458
|
+
) # Use banner_printed to track if we've shown tool info
|
|
1446
1459
|
|
|
1447
1460
|
# PartDeltaEvent - stream the content as it arrives
|
|
1448
1461
|
elif isinstance(event, PartDeltaEvent):
|
|
@@ -1460,7 +1473,10 @@ class BaseAgent(ABC):
|
|
|
1460
1473
|
banner_printed.add(event.index)
|
|
1461
1474
|
# Accumulate text for final markdown render
|
|
1462
1475
|
text_buffer[event.index].append(delta.content_delta)
|
|
1463
|
-
|
|
1476
|
+
# Use len(content) / 3 for token estimation
|
|
1477
|
+
token_count[event.index] += (
|
|
1478
|
+
len(delta.content_delta) // 3
|
|
1479
|
+
)
|
|
1464
1480
|
# Update token counter in place (single line)
|
|
1465
1481
|
count = token_count[event.index]
|
|
1466
1482
|
sys.stdout.write(
|
|
@@ -1474,14 +1490,32 @@ class BaseAgent(ABC):
|
|
|
1474
1490
|
banner_printed.add(event.index)
|
|
1475
1491
|
escaped = escape(delta.content_delta)
|
|
1476
1492
|
console.print(f"[dim]{escaped}[/dim]", end="")
|
|
1493
|
+
elif isinstance(delta, ToolCallPartDelta):
|
|
1494
|
+
import sys
|
|
1495
|
+
|
|
1496
|
+
# For tool calls, show token counter (use string repr for estimation)
|
|
1497
|
+
token_count[event.index] += len(str(delta)) // 3
|
|
1498
|
+
# Get tool name if available
|
|
1499
|
+
tool_name = getattr(delta, "tool_name_delta", "")
|
|
1500
|
+
count = token_count[event.index]
|
|
1501
|
+
# Display with tool wrench icon and tool name
|
|
1502
|
+
if tool_name:
|
|
1503
|
+
sys.stdout.write(
|
|
1504
|
+
f"\r\x1b[K 🔧 Calling {tool_name}... {count} tokens"
|
|
1505
|
+
)
|
|
1506
|
+
else:
|
|
1507
|
+
sys.stdout.write(
|
|
1508
|
+
f"\r\x1b[K 🔧 Calling tool... {count} tokens"
|
|
1509
|
+
)
|
|
1510
|
+
sys.stdout.flush()
|
|
1477
1511
|
|
|
1478
1512
|
# PartEndEvent - finish the streaming with a newline
|
|
1479
1513
|
elif isinstance(event, PartEndEvent):
|
|
1480
1514
|
if event.index in streaming_parts:
|
|
1515
|
+
import sys
|
|
1516
|
+
|
|
1481
1517
|
# For text parts, clear counter line and render markdown
|
|
1482
1518
|
if event.index in text_parts:
|
|
1483
|
-
import sys
|
|
1484
|
-
|
|
1485
1519
|
# Clear the token counter line
|
|
1486
1520
|
sys.stdout.write("\r\x1b[K")
|
|
1487
1521
|
sys.stdout.flush()
|
|
@@ -1494,24 +1528,31 @@ class BaseAgent(ABC):
|
|
|
1494
1528
|
except Exception:
|
|
1495
1529
|
pass
|
|
1496
1530
|
del text_buffer[event.index]
|
|
1497
|
-
|
|
1498
|
-
|
|
1531
|
+
# For tool parts, clear the token counter line
|
|
1532
|
+
elif event.index in tool_parts:
|
|
1533
|
+
# Clear the token counter line
|
|
1534
|
+
sys.stdout.write("\r\x1b[K")
|
|
1535
|
+
sys.stdout.flush()
|
|
1499
1536
|
# For thinking parts, just print newline
|
|
1500
1537
|
elif event.index in banner_printed:
|
|
1501
1538
|
console.print() # Final newline after streaming
|
|
1539
|
+
|
|
1540
|
+
# Clean up token count
|
|
1541
|
+
token_count.pop(event.index, None)
|
|
1502
1542
|
# Clean up all tracking sets
|
|
1503
1543
|
streaming_parts.discard(event.index)
|
|
1504
1544
|
thinking_parts.discard(event.index)
|
|
1505
1545
|
text_parts.discard(event.index)
|
|
1546
|
+
tool_parts.discard(event.index)
|
|
1506
1547
|
banner_printed.discard(event.index)
|
|
1507
1548
|
|
|
1508
|
-
# Resume spinner if next part is NOT text/thinking (avoid race condition)
|
|
1509
|
-
# If next part is
|
|
1549
|
+
# Resume spinner if next part is NOT text/thinking/tool (avoid race condition)
|
|
1550
|
+
# If next part is None or handled differently, it's safe to resume
|
|
1510
1551
|
# Note: spinner itself handles blank line before appearing
|
|
1511
1552
|
from code_puppy.messaging.spinner import resume_all_spinners
|
|
1512
1553
|
|
|
1513
1554
|
next_kind = getattr(event, "next_part_kind", None)
|
|
1514
|
-
if next_kind not in ("text", "thinking"):
|
|
1555
|
+
if next_kind not in ("text", "thinking", "tool-call"):
|
|
1515
1556
|
resume_all_spinners()
|
|
1516
1557
|
|
|
1517
1558
|
# Spinner is resumed in PartEndEvent when appropriate (based on next_part_kind)
|
|
@@ -1910,73 +1951,32 @@ class BaseAgent(ABC):
|
|
|
1910
1951
|
def graceful_sigint_handler(_sig, _frame):
|
|
1911
1952
|
# When using keyboard-based cancel, SIGINT should be a no-op
|
|
1912
1953
|
# (just show a hint to user about the configured cancel key)
|
|
1913
|
-
from code_puppy.keymap import get_cancel_agent_display_name
|
|
1914
1954
|
import sys
|
|
1915
1955
|
|
|
1956
|
+
from code_puppy.keymap import get_cancel_agent_display_name
|
|
1957
|
+
|
|
1916
1958
|
cancel_key = get_cancel_agent_display_name()
|
|
1917
|
-
|
|
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.")
|
|
1959
|
+
emit_info(f"Use {cancel_key} to cancel the agent task.")
|
|
1923
1960
|
|
|
1924
1961
|
original_handler = None
|
|
1925
1962
|
key_listener_stop_event = None
|
|
1926
1963
|
_key_listener_thread = None
|
|
1927
|
-
_windows_ctrl_handler = None # Store reference to prevent garbage collection
|
|
1928
1964
|
|
|
1929
1965
|
try:
|
|
1930
|
-
if
|
|
1931
|
-
#
|
|
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
|
|
1966
|
+
if cancel_agent_uses_signal():
|
|
1967
|
+
# Use SIGINT-based cancellation (default Ctrl+C behavior)
|
|
1970
1968
|
original_handler = signal.signal(
|
|
1971
1969
|
signal.SIGINT, keyboard_interrupt_handler
|
|
1972
1970
|
)
|
|
1973
1971
|
else:
|
|
1974
|
-
#
|
|
1972
|
+
# Use keyboard listener for agent cancellation
|
|
1973
|
+
# Set a graceful SIGINT handler that shows a hint
|
|
1975
1974
|
original_handler = signal.signal(signal.SIGINT, graceful_sigint_handler)
|
|
1975
|
+
# Spawn keyboard listener with the cancel agent callback
|
|
1976
1976
|
key_listener_stop_event = threading.Event()
|
|
1977
1977
|
_key_listener_thread = self._spawn_ctrl_x_key_listener(
|
|
1978
1978
|
key_listener_stop_event,
|
|
1979
|
-
on_escape=lambda: None,
|
|
1979
|
+
on_escape=lambda: None, # Ctrl+X handled by command_runner
|
|
1980
1980
|
on_cancel_agent=schedule_agent_cancel,
|
|
1981
1981
|
)
|
|
1982
1982
|
|
|
@@ -2001,17 +2001,8 @@ class BaseAgent(ABC):
|
|
|
2001
2001
|
# Stop keyboard listener if it was started
|
|
2002
2002
|
if key_listener_stop_event is not None:
|
|
2003
2003
|
key_listener_stop_event.set()
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
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:
|
|
2004
|
+
# Restore original signal handler
|
|
2005
|
+
if (
|
|
2006
|
+
original_handler is not None
|
|
2007
|
+
): # Explicit None check - SIG_DFL can be 0/falsy!
|
|
2017
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()
|
|
@@ -571,6 +571,7 @@ class AddModelMenu:
|
|
|
571
571
|
"cerebras": "cerebras",
|
|
572
572
|
"cohere": "custom_openai",
|
|
573
573
|
"perplexity": "custom_openai",
|
|
574
|
+
"minimax": "custom_anthropic",
|
|
574
575
|
}
|
|
575
576
|
|
|
576
577
|
# Determine the model type
|
|
@@ -600,6 +601,16 @@ class AddModelMenu:
|
|
|
600
601
|
api_key_env = f"${provider.env[0]}" if provider.env else "$API_KEY"
|
|
601
602
|
config["custom_endpoint"] = {"url": api_url, "api_key": api_key_env}
|
|
602
603
|
|
|
604
|
+
# Special handling for minimax: uses custom_anthropic but needs custom_endpoint
|
|
605
|
+
# and the URL needs /v1 stripped (comes as https://api.minimax.io/anthropic/v1)
|
|
606
|
+
if provider.id == "minimax" and provider.api:
|
|
607
|
+
api_url = provider.api
|
|
608
|
+
# Strip /v1 suffix if present
|
|
609
|
+
if api_url.endswith("/v1"):
|
|
610
|
+
api_url = api_url[:-3]
|
|
611
|
+
api_key_env = f"${provider.env[0]}" if provider.env else "$API_KEY"
|
|
612
|
+
config["custom_endpoint"] = {"url": api_url, "api_key": api_key_env}
|
|
613
|
+
|
|
603
614
|
# Add context length if available
|
|
604
615
|
if model.context_length and model.context_length > 0:
|
|
605
616
|
config["context_length"] = model.context_length
|
|
@@ -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
|
|
|
@@ -18,6 +18,9 @@ def _load_builtin_plugins(plugins_dir: Path) -> list[str]:
|
|
|
18
18
|
|
|
19
19
|
Returns list of successfully loaded plugin names.
|
|
20
20
|
"""
|
|
21
|
+
# Import safety permission check for shell_safety plugin
|
|
22
|
+
from code_puppy.config import get_safety_permission_level
|
|
23
|
+
|
|
21
24
|
loaded = []
|
|
22
25
|
|
|
23
26
|
for item in plugins_dir.iterdir():
|
|
@@ -26,6 +29,15 @@ def _load_builtin_plugins(plugins_dir: Path) -> list[str]:
|
|
|
26
29
|
callbacks_file = item / "register_callbacks.py"
|
|
27
30
|
|
|
28
31
|
if callbacks_file.exists():
|
|
32
|
+
# Skip shell_safety plugin unless safety_permission_level is "low" or "none"
|
|
33
|
+
if plugin_name == "shell_safety":
|
|
34
|
+
safety_level = get_safety_permission_level()
|
|
35
|
+
if safety_level not in ("none", "low"):
|
|
36
|
+
logger.debug(
|
|
37
|
+
f"Skipping shell_safety plugin - safety_permission_level is '{safety_level}' (needs 'low' or 'none')"
|
|
38
|
+
)
|
|
39
|
+
continue
|
|
40
|
+
|
|
29
41
|
try:
|
|
30
42
|
module_name = f"code_puppy.plugins.{plugin_name}.register_callbacks"
|
|
31
43
|
importlib.import_module(module_name)
|
|
@@ -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
|
|
File without changes
|
{code_puppy-0.0.324 → code_puppy-0.0.326}/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.324 → code_puppy-0.0.326}/code_puppy/command_line/mcp/catalog_server_installer.py
RENAMED
|
File without changes
|
|
File without changes
|
{code_puppy-0.0.324 → code_puppy-0.0.326}/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.324 → code_puppy-0.0.326}/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.324 → code_puppy-0.0.326}/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.324 → code_puppy-0.0.326}/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.324 → code_puppy-0.0.326}/code_puppy/plugins/claude_code_oauth/register_callbacks.py
RENAMED
|
File without changes
|
{code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/plugins/claude_code_oauth/test_plugin.py
RENAMED
|
File without changes
|
|
File without changes
|
{code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/plugins/customizable_commands/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{code_puppy-0.0.324 → code_puppy-0.0.326}/code_puppy/plugins/example_custom_command/README.md
RENAMED
|
File without changes
|
|
File without changes
|
{code_puppy-0.0.324 → code_puppy-0.0.326}/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.324 → code_puppy-0.0.326}/code_puppy/plugins/shell_safety/agent_shell_safety.py
RENAMED
|
File without changes
|
|
File without changes
|
{code_puppy-0.0.324 → code_puppy-0.0.326}/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
|