code-puppy 0.0.335__tar.gz → 0.0.336__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.335 → code_puppy-0.0.336}/PKG-INFO +1 -1
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/messaging/rich_renderer.py +101 -19
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/plugins/antigravity_oauth/antigravity_model.py +50 -9
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/plugins/antigravity_oauth/transport.py +127 -58
- {code_puppy-0.0.335 → code_puppy-0.0.336}/pyproject.toml +1 -1
- {code_puppy-0.0.335 → code_puppy-0.0.336}/.gitignore +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/LICENSE +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/README.md +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/__init__.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/__main__.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/agents/__init__.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/agents/agent_c_reviewer.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/agents/agent_code_puppy.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/agents/agent_code_reviewer.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/agents/agent_cpp_reviewer.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/agents/agent_creator_agent.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/agents/agent_golang_reviewer.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/agents/agent_javascript_reviewer.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/agents/agent_manager.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/agents/agent_planning.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/agents/agent_python_programmer.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/agents/agent_python_reviewer.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/agents/agent_qa_expert.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/agents/agent_qa_kitten.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/agents/agent_security_auditor.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/agents/agent_typescript_reviewer.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/agents/base_agent.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/agents/json_agent.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/agents/prompt_reviewer.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/callbacks.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/chatgpt_codex_client.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/claude_cache_client.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/cli_runner.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/__init__.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/add_model_menu.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/attachments.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/autosave_menu.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/colors_menu.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/command_handler.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/command_registry.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/config_commands.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/core_commands.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/diff_menu.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/file_path_completion.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/load_context_completion.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/mcp/__init__.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/mcp/add_command.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/mcp/base.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/mcp/catalog_server_installer.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/mcp/custom_server_form.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/mcp/custom_server_installer.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/mcp/edit_command.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/mcp/handler.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/mcp/help_command.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/mcp/install_command.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/mcp/install_menu.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/mcp/list_command.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/mcp/logs_command.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/mcp/remove_command.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/mcp/restart_command.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/mcp/search_command.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/mcp/start_all_command.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/mcp/start_command.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/mcp/status_command.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/mcp/stop_all_command.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/mcp/stop_command.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/mcp/test_command.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/mcp/utils.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/mcp/wizard_utils.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/mcp_completion.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/model_picker_completion.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/model_settings_menu.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/motd.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/onboarding_slides.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/onboarding_wizard.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/pin_command_completion.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/prompt_toolkit_completion.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/session_commands.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/command_line/utils.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/config.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/error_logging.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/gemini_code_assist.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/http_utils.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/keymap.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/main.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/mcp_/__init__.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/mcp_/async_lifecycle.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/mcp_/blocking_startup.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/mcp_/captured_stdio_server.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/mcp_/circuit_breaker.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/mcp_/config_wizard.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/mcp_/dashboard.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/mcp_/error_isolation.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/mcp_/examples/retry_example.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/mcp_/health_monitor.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/mcp_/managed_server.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/mcp_/manager.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/mcp_/mcp_logs.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/mcp_/registry.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/mcp_/retry_manager.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/mcp_/server_registry_catalog.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/mcp_/status_tracker.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/mcp_/system_tools.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/messaging/__init__.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/messaging/bus.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/messaging/commands.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/messaging/markdown_patches.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/messaging/message_queue.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/messaging/messages.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/messaging/queue_console.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/messaging/renderers.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/messaging/spinner/__init__.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/messaging/spinner/console_spinner.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/messaging/spinner/spinner_base.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/model_factory.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/model_utils.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/models.json +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/models_dev_api.json +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/models_dev_parser.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/plugins/__init__.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/plugins/antigravity_oauth/__init__.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/plugins/antigravity_oauth/accounts.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/plugins/antigravity_oauth/config.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/plugins/antigravity_oauth/constants.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/plugins/antigravity_oauth/oauth.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/plugins/antigravity_oauth/register_callbacks.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/plugins/antigravity_oauth/storage.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/plugins/antigravity_oauth/test_plugin.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/plugins/antigravity_oauth/token.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/plugins/antigravity_oauth/utils.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/plugins/chatgpt_oauth/__init__.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/plugins/chatgpt_oauth/config.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/plugins/chatgpt_oauth/oauth_flow.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/plugins/chatgpt_oauth/register_callbacks.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/plugins/chatgpt_oauth/test_plugin.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/plugins/chatgpt_oauth/utils.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/plugins/claude_code_oauth/README.md +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/plugins/claude_code_oauth/SETUP.md +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/plugins/claude_code_oauth/__init__.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/plugins/claude_code_oauth/config.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/plugins/claude_code_oauth/register_callbacks.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/plugins/claude_code_oauth/test_plugin.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/plugins/claude_code_oauth/utils.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/plugins/customizable_commands/__init__.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/plugins/customizable_commands/register_callbacks.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/plugins/example_custom_command/README.md +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/plugins/example_custom_command/register_callbacks.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/plugins/file_permission_handler/__init__.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/plugins/file_permission_handler/register_callbacks.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/plugins/oauth_puppy_html.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/plugins/shell_safety/__init__.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/plugins/shell_safety/agent_shell_safety.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/plugins/shell_safety/command_cache.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/plugins/shell_safety/register_callbacks.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/prompts/codex_system_prompt.md +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/pydantic_patches.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/reopenable_async_client.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/round_robin_model.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/session_storage.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/status_display.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/summarization_agent.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/terminal_utils.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/tools/__init__.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/tools/agent_tools.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/tools/browser/__init__.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/tools/browser/browser_control.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/tools/browser/browser_interactions.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/tools/browser/browser_locators.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/tools/browser/browser_navigation.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/tools/browser/browser_screenshot.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/tools/browser/browser_scripts.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/tools/browser/browser_workflows.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/tools/browser/camoufox_manager.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/tools/browser/vqa_agent.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/tools/command_runner.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/tools/common.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/tools/file_modifications.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/tools/file_operations.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/tools/tools_content.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/uvx_detection.py +0 -0
- {code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/version_checker.py +0 -0
|
@@ -348,7 +348,17 @@ class RichConsoleRenderer:
|
|
|
348
348
|
# =========================================================================
|
|
349
349
|
|
|
350
350
|
def _render_file_listing(self, msg: FileListingMessage) -> None:
|
|
351
|
-
"""Render a directory listing
|
|
351
|
+
"""Render a compact directory listing with directory summaries.
|
|
352
|
+
|
|
353
|
+
Instead of listing every file, we group by directory and show:
|
|
354
|
+
- Directory name
|
|
355
|
+
- Number of files
|
|
356
|
+
- Total size
|
|
357
|
+
- Number of subdirectories
|
|
358
|
+
"""
|
|
359
|
+
import os
|
|
360
|
+
from collections import defaultdict
|
|
361
|
+
|
|
352
362
|
# Header on single line
|
|
353
363
|
rec_flag = f"(recursive={msg.recursive})"
|
|
354
364
|
banner = self._format_banner("directory_listing", "DIRECTORY LISTING")
|
|
@@ -357,32 +367,104 @@ class RichConsoleRenderer:
|
|
|
357
367
|
f"📂 [bold cyan]{msg.directory}[/bold cyan] [dim]{rec_flag}[/dim]\n"
|
|
358
368
|
)
|
|
359
369
|
|
|
360
|
-
#
|
|
361
|
-
|
|
362
|
-
|
|
370
|
+
# Build a tree structure: {parent_path: {files: [], dirs: set(), size: int}}
|
|
371
|
+
# Each key is a directory path, value contains direct children stats
|
|
372
|
+
dir_stats: dict = defaultdict(
|
|
373
|
+
lambda: {"files": [], "subdirs": set(), "total_size": 0}
|
|
374
|
+
)
|
|
375
|
+
|
|
376
|
+
# Root directory is represented as ""
|
|
377
|
+
root_key = ""
|
|
363
378
|
|
|
364
|
-
# Build tree structure from flat list
|
|
365
379
|
for entry in msg.files:
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
for d in range(entry.depth + 1):
|
|
369
|
-
if d == entry.depth:
|
|
370
|
-
prefix += "└── "
|
|
371
|
-
else:
|
|
372
|
-
prefix += " "
|
|
380
|
+
path = entry.path
|
|
381
|
+
parent = os.path.dirname(path) if os.path.dirname(path) else root_key
|
|
373
382
|
|
|
374
383
|
if entry.type == "dir":
|
|
375
|
-
|
|
384
|
+
# Register this dir as a subdir of its parent
|
|
385
|
+
dir_stats[parent]["subdirs"].add(path)
|
|
386
|
+
# Ensure the dir itself exists in stats (even if empty)
|
|
387
|
+
_ = dir_stats[path]
|
|
376
388
|
else:
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
389
|
+
# It's a file - add to parent's stats
|
|
390
|
+
dir_stats[parent]["files"].append(entry)
|
|
391
|
+
dir_stats[parent]["total_size"] += entry.size
|
|
392
|
+
|
|
393
|
+
def render_dir_tree(dir_path: str, depth: int = 0) -> None:
|
|
394
|
+
"""Recursively render directory with compact summary."""
|
|
395
|
+
stats = dir_stats.get(
|
|
396
|
+
dir_path, {"files": [], "subdirs": set(), "total_size": 0}
|
|
397
|
+
)
|
|
398
|
+
files = stats["files"]
|
|
399
|
+
subdirs = sorted(stats["subdirs"])
|
|
400
|
+
|
|
401
|
+
# Calculate total size including subdirectories (recursive)
|
|
402
|
+
def get_recursive_size(d: str) -> int:
|
|
403
|
+
s = dir_stats.get(d, {"files": [], "subdirs": set(), "total_size": 0})
|
|
404
|
+
size = s["total_size"]
|
|
405
|
+
for sub in s["subdirs"]:
|
|
406
|
+
size += get_recursive_size(sub)
|
|
407
|
+
return size
|
|
408
|
+
|
|
409
|
+
def get_recursive_file_count(d: str) -> int:
|
|
410
|
+
s = dir_stats.get(d, {"files": [], "subdirs": set(), "total_size": 0})
|
|
411
|
+
count = len(s["files"])
|
|
412
|
+
for sub in s["subdirs"]:
|
|
413
|
+
count += get_recursive_file_count(sub)
|
|
414
|
+
return count
|
|
415
|
+
|
|
416
|
+
indent = " " * depth
|
|
417
|
+
|
|
418
|
+
# For root level, just show contents
|
|
419
|
+
if dir_path == root_key:
|
|
420
|
+
# Show files at root level (depth 0)
|
|
421
|
+
for f in sorted(files, key=lambda x: x.path):
|
|
422
|
+
icon = self._get_file_icon(f.path)
|
|
423
|
+
name = os.path.basename(f.path)
|
|
424
|
+
size_str = (
|
|
425
|
+
f" [dim]({self._format_size(f.size)})[/dim]"
|
|
426
|
+
if f.size > 0
|
|
427
|
+
else ""
|
|
428
|
+
)
|
|
429
|
+
self._console.print(
|
|
430
|
+
f"{indent}{icon} [green]{name}[/green]{size_str}"
|
|
431
|
+
)
|
|
432
|
+
|
|
433
|
+
# Show subdirs at root level
|
|
434
|
+
for subdir in subdirs:
|
|
435
|
+
render_dir_tree(subdir, depth)
|
|
436
|
+
else:
|
|
437
|
+
# Show directory with summary
|
|
438
|
+
dir_name = os.path.basename(dir_path)
|
|
439
|
+
rec_size = get_recursive_size(dir_path)
|
|
440
|
+
rec_file_count = get_recursive_file_count(dir_path)
|
|
441
|
+
subdir_count = len(subdirs)
|
|
442
|
+
|
|
443
|
+
# Build summary parts
|
|
444
|
+
parts = []
|
|
445
|
+
if rec_file_count > 0:
|
|
446
|
+
parts.append(
|
|
447
|
+
f"{rec_file_count} file{'s' if rec_file_count != 1 else ''}"
|
|
448
|
+
)
|
|
449
|
+
if subdir_count > 0:
|
|
450
|
+
parts.append(
|
|
451
|
+
f"{subdir_count} subdir{'s' if subdir_count != 1 else ''}"
|
|
452
|
+
)
|
|
453
|
+
if rec_size > 0:
|
|
454
|
+
parts.append(self._format_size(rec_size))
|
|
455
|
+
|
|
456
|
+
summary = f" [dim]({', '.join(parts)})[/dim]" if parts else ""
|
|
382
457
|
self._console.print(
|
|
383
|
-
f"{
|
|
458
|
+
f"{indent}📁 [bold blue]{dir_name}/[/bold blue]{summary}"
|
|
384
459
|
)
|
|
385
460
|
|
|
461
|
+
# Recursively show subdirectories
|
|
462
|
+
for subdir in subdirs:
|
|
463
|
+
render_dir_tree(subdir, depth + 1)
|
|
464
|
+
|
|
465
|
+
# Render the tree starting from root
|
|
466
|
+
render_dir_tree(root_key, 0)
|
|
467
|
+
|
|
386
468
|
# Summary
|
|
387
469
|
self._console.print("\n[bold cyan]Summary:[/bold cyan]")
|
|
388
470
|
self._console.print(
|
{code_puppy-0.0.335 → code_puppy-0.0.336}/code_puppy/plugins/antigravity_oauth/antigravity_model.py
RENAMED
|
@@ -54,7 +54,15 @@ class AntigravityModel(GoogleModel):
|
|
|
54
54
|
messages: list[ModelMessage],
|
|
55
55
|
model_request_parameters: ModelRequestParameters,
|
|
56
56
|
) -> tuple[ContentDict | None, list[dict]]:
|
|
57
|
-
"""Map messages to Google GenAI format, preserving thinking signatures.
|
|
57
|
+
"""Map messages to Google GenAI format, preserving thinking signatures.
|
|
58
|
+
|
|
59
|
+
IMPORTANT: For Gemini with parallel function calls, the API expects:
|
|
60
|
+
- Model message: [FC1 + signature, FC2, ...] (all function calls together)
|
|
61
|
+
- User message: [FR1, FR2, ...] (all function responses together)
|
|
62
|
+
|
|
63
|
+
If messages are interleaved (FC1, FR1, FC2, FR2), the API returns 400.
|
|
64
|
+
This method merges consecutive same-role messages to fix this.
|
|
65
|
+
"""
|
|
58
66
|
contents: list[dict] = []
|
|
59
67
|
system_parts: list[PartDict] = []
|
|
60
68
|
|
|
@@ -95,7 +103,12 @@ class AntigravityModel(GoogleModel):
|
|
|
95
103
|
assert_never(part)
|
|
96
104
|
|
|
97
105
|
if message_parts:
|
|
98
|
-
|
|
106
|
+
# Merge with previous user message if exists (for parallel function responses)
|
|
107
|
+
if contents and contents[-1].get("role") == "user":
|
|
108
|
+
contents[-1]["parts"].extend(message_parts)
|
|
109
|
+
else:
|
|
110
|
+
contents.append({"role": "user", "parts": message_parts})
|
|
111
|
+
|
|
99
112
|
elif isinstance(m, ModelResponse):
|
|
100
113
|
# USE CUSTOM HELPER HERE
|
|
101
114
|
# Pass model name so we can handle Claude vs Gemini signature placement
|
|
@@ -103,7 +116,11 @@ class AntigravityModel(GoogleModel):
|
|
|
103
116
|
m, self.system, self._model_name
|
|
104
117
|
)
|
|
105
118
|
if maybe_content:
|
|
106
|
-
|
|
119
|
+
# Merge with previous model message if exists (for parallel function calls)
|
|
120
|
+
if contents and contents[-1].get("role") == "model":
|
|
121
|
+
contents[-1]["parts"].extend(maybe_content["parts"])
|
|
122
|
+
else:
|
|
123
|
+
contents.append(maybe_content)
|
|
107
124
|
else:
|
|
108
125
|
assert_never(m)
|
|
109
126
|
|
|
@@ -435,6 +452,13 @@ class AntigravityStreamingResponse(StreamedResponse):
|
|
|
435
452
|
return self._timestamp_val
|
|
436
453
|
|
|
437
454
|
|
|
455
|
+
# Bypass signature for when no real thought signature is available.
|
|
456
|
+
# Gemini API requires EVERY function call to have a thoughtSignature field.
|
|
457
|
+
# When there's no thinking block or no signature was captured, we use this bypass.
|
|
458
|
+
# This specific key is the official bypass token for Gemini 3 Pro.
|
|
459
|
+
BYPASS_THOUGHT_SIGNATURE = "context_engineering_is_the_way_to_go"
|
|
460
|
+
|
|
461
|
+
|
|
438
462
|
def _antigravity_content_model_response(
|
|
439
463
|
m: ModelResponse, provider_name: str, model_name: str = ""
|
|
440
464
|
) -> ContentDict | None:
|
|
@@ -443,6 +467,10 @@ def _antigravity_content_model_response(
|
|
|
443
467
|
Handles different signature protocols:
|
|
444
468
|
- Claude models: signature goes ON the thinking block itself
|
|
445
469
|
- Gemini models: signature goes on the NEXT part (function_call or text) after thinking
|
|
470
|
+
|
|
471
|
+
IMPORTANT: For Gemini, EVERY function call MUST have a thoughtSignature field.
|
|
472
|
+
If no real signature is available (no preceding ThinkingPart, or ThinkingPart
|
|
473
|
+
had no signature), we use BYPASS_THOUGHT_SIGNATURE as a fallback.
|
|
446
474
|
"""
|
|
447
475
|
parts: list[PartDict] = []
|
|
448
476
|
|
|
@@ -451,6 +479,7 @@ def _antigravity_content_model_response(
|
|
|
451
479
|
is_gemini = "gemini" in model_name.lower()
|
|
452
480
|
|
|
453
481
|
# For Gemini: save signature from ThinkingPart to attach to next part
|
|
482
|
+
# Initialize to None - we'll use BYPASS_THOUGHT_SIGNATURE if still None when needed
|
|
454
483
|
pending_signature: str | None = None
|
|
455
484
|
|
|
456
485
|
for item in m.parts:
|
|
@@ -462,16 +491,24 @@ def _antigravity_content_model_response(
|
|
|
462
491
|
)
|
|
463
492
|
part["function_call"] = function_call
|
|
464
493
|
|
|
465
|
-
# For Gemini: attach
|
|
466
|
-
if
|
|
467
|
-
|
|
468
|
-
|
|
494
|
+
# For Gemini: ALWAYS attach a thoughtSignature to function calls.
|
|
495
|
+
# Use the real signature if available, otherwise use bypass.
|
|
496
|
+
# NOTE: Do NOT clear pending_signature here! Multiple tool calls
|
|
497
|
+
# in a row (e.g., parallel function calls) all need the same
|
|
498
|
+
# signature from the preceding ThinkingPart.
|
|
499
|
+
if is_gemini:
|
|
500
|
+
part["thoughtSignature"] = (
|
|
501
|
+
pending_signature
|
|
502
|
+
if pending_signature is not None
|
|
503
|
+
else BYPASS_THOUGHT_SIGNATURE
|
|
504
|
+
)
|
|
469
505
|
|
|
470
506
|
elif isinstance(item, TextPart):
|
|
471
507
|
part["text"] = item.content
|
|
472
508
|
|
|
473
|
-
# For Gemini: attach pending signature to text part
|
|
474
|
-
|
|
509
|
+
# For Gemini: attach pending signature to text part if available
|
|
510
|
+
# Clear signature after text since text typically ends a response
|
|
511
|
+
if is_gemini and pending_signature is not None:
|
|
475
512
|
part["thoughtSignature"] = pending_signature
|
|
476
513
|
pending_signature = None
|
|
477
514
|
|
|
@@ -490,6 +527,10 @@ def _antigravity_content_model_response(
|
|
|
490
527
|
else:
|
|
491
528
|
# Default: try both (put on thinking block)
|
|
492
529
|
part["thoughtSignature"] = item.signature
|
|
530
|
+
elif is_gemini:
|
|
531
|
+
# ThinkingPart exists but has no signature - use bypass
|
|
532
|
+
# This ensures subsequent tool calls still get a signature
|
|
533
|
+
pending_signature = BYPASS_THOUGHT_SIGNATURE
|
|
493
534
|
|
|
494
535
|
elif isinstance(item, BuiltinToolCallPart):
|
|
495
536
|
# Skip code execution for now
|
|
@@ -422,6 +422,8 @@ class AntigravityClient(httpx.AsyncClient):
|
|
|
422
422
|
|
|
423
423
|
async def send(self, request: httpx.Request, **kwargs: Any) -> httpx.Response:
|
|
424
424
|
"""Override send to intercept at the lowest level with endpoint fallback."""
|
|
425
|
+
import asyncio
|
|
426
|
+
|
|
425
427
|
# Transform POST requests to Antigravity format
|
|
426
428
|
if request.method == "POST" and request.content:
|
|
427
429
|
new_content, new_path, new_query, is_claude_thinking = self._wrap_request(
|
|
@@ -467,25 +469,21 @@ class AntigravityClient(httpx.AsyncClient):
|
|
|
467
469
|
else:
|
|
468
470
|
new_headers["anthropic-beta"] = interleaved_header
|
|
469
471
|
|
|
470
|
-
# Try each endpoint
|
|
472
|
+
# Try each endpoint with rate limit retry logic
|
|
471
473
|
last_response = None
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
path=new_path,
|
|
486
|
-
query=new_query.encode() if new_query else b"",
|
|
487
|
-
)
|
|
488
|
-
|
|
474
|
+
max_rate_limit_retries = 5 # Max retries for 429s per endpoint
|
|
475
|
+
|
|
476
|
+
for endpoint in ANTIGRAVITY_ENDPOINT_FALLBACKS:
|
|
477
|
+
# Build URL with current endpoint
|
|
478
|
+
new_url = httpx.URL(
|
|
479
|
+
scheme="https",
|
|
480
|
+
host=endpoint.replace("https://", ""),
|
|
481
|
+
path=new_path,
|
|
482
|
+
query=new_query.encode() if new_query else b"",
|
|
483
|
+
)
|
|
484
|
+
|
|
485
|
+
# Retry loop for rate limits on this endpoint
|
|
486
|
+
for rate_limit_attempt in range(max_rate_limit_retries):
|
|
489
487
|
req = httpx.Request(
|
|
490
488
|
method=request.method,
|
|
491
489
|
url=new_url,
|
|
@@ -498,45 +496,35 @@ class AntigravityClient(httpx.AsyncClient):
|
|
|
498
496
|
|
|
499
497
|
# Handle rate limit (429)
|
|
500
498
|
if response.status_code == 429:
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
reset_delay = 2.0 # Default fallback
|
|
508
|
-
if isinstance(error_data, dict):
|
|
509
|
-
error_info = error_data.get("error", {})
|
|
510
|
-
if isinstance(error_info, dict):
|
|
511
|
-
details = error_info.get("details", [])
|
|
512
|
-
for detail in details:
|
|
513
|
-
metadata = detail.get("metadata", {})
|
|
514
|
-
if "quotaResetDelay" in metadata:
|
|
515
|
-
delay_str = metadata["quotaResetDelay"]
|
|
516
|
-
if delay_str.endswith("s"):
|
|
517
|
-
reset_delay = float(delay_str[:-1])
|
|
518
|
-
break
|
|
519
|
-
|
|
520
|
-
# Only retry if delay is reasonable (< 60s)
|
|
521
|
-
if reset_delay < 60:
|
|
522
|
-
# Add small buffer
|
|
523
|
-
wait_time = reset_delay + 0.5
|
|
499
|
+
wait_time = await self._extract_rate_limit_delay(response)
|
|
500
|
+
|
|
501
|
+
if wait_time is not None and wait_time < 60:
|
|
502
|
+
# Add small buffer to wait time
|
|
503
|
+
wait_time = wait_time + 0.1
|
|
504
|
+
try:
|
|
524
505
|
from code_puppy.messaging import emit_warning
|
|
525
506
|
|
|
526
507
|
emit_warning(
|
|
527
|
-
f"⏳ Rate limited
|
|
508
|
+
f"⏳ Rate limited (attempt {rate_limit_attempt + 1}/{max_rate_limit_retries}). "
|
|
509
|
+
f"Waiting {wait_time:.2f}s..."
|
|
528
510
|
)
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
emit_warning(
|
|
533
|
-
f"❌ Rate limit reset too long ({reset_delay}s). Aborting."
|
|
511
|
+
except ImportError:
|
|
512
|
+
logger.warning(
|
|
513
|
+
"Rate limited, waiting %.2fs...", wait_time
|
|
534
514
|
)
|
|
535
|
-
return UnwrappedResponse(response)
|
|
536
|
-
except Exception:
|
|
537
|
-
pass # Failed to parse error, treat as normal error
|
|
538
515
|
|
|
539
|
-
|
|
516
|
+
await asyncio.sleep(wait_time)
|
|
517
|
+
continue # Retry same endpoint
|
|
518
|
+
else:
|
|
519
|
+
# Wait time too long or couldn't parse, try next endpoint
|
|
520
|
+
logger.debug(
|
|
521
|
+
"Rate limit wait too long (%.1fs) on %s, trying next endpoint...",
|
|
522
|
+
wait_time or 0,
|
|
523
|
+
endpoint,
|
|
524
|
+
)
|
|
525
|
+
break # Break inner loop, try next endpoint
|
|
526
|
+
|
|
527
|
+
# Retry on 403, 404, 5xx errors - try next endpoint
|
|
540
528
|
if (
|
|
541
529
|
response.status_code in (403, 404)
|
|
542
530
|
or response.status_code >= 500
|
|
@@ -546,9 +534,9 @@ class AntigravityClient(httpx.AsyncClient):
|
|
|
546
534
|
endpoint,
|
|
547
535
|
response.status_code,
|
|
548
536
|
)
|
|
549
|
-
|
|
537
|
+
break # Try next endpoint
|
|
550
538
|
|
|
551
|
-
# Success or non-retriable error
|
|
539
|
+
# Success or non-retriable error (4xx except 429)
|
|
552
540
|
# Wrap response to unwrap Antigravity format
|
|
553
541
|
if "alt=sse" in new_query:
|
|
554
542
|
return UnwrappedSSEResponse(response)
|
|
@@ -558,15 +546,96 @@ class AntigravityClient(httpx.AsyncClient):
|
|
|
558
546
|
await response.aread()
|
|
559
547
|
return UnwrappedResponse(response)
|
|
560
548
|
|
|
561
|
-
# All endpoints
|
|
562
|
-
if last_response
|
|
563
|
-
|
|
549
|
+
# All endpoints/retries exhausted, return last response
|
|
550
|
+
if last_response:
|
|
551
|
+
# Ensure response is read for proper error handling
|
|
552
|
+
if not last_response.is_stream_consumed:
|
|
553
|
+
try:
|
|
554
|
+
await last_response.aread()
|
|
555
|
+
except Exception:
|
|
556
|
+
pass
|
|
564
557
|
return UnwrappedResponse(last_response)
|
|
565
558
|
|
|
566
|
-
return last_response
|
|
567
|
-
|
|
568
559
|
return await super().send(request, **kwargs)
|
|
569
560
|
|
|
561
|
+
async def _extract_rate_limit_delay(self, response: httpx.Response) -> float | None:
|
|
562
|
+
"""Extract the retry delay from a 429 rate limit response.
|
|
563
|
+
|
|
564
|
+
Parses the Antigravity/Google API error format to find:
|
|
565
|
+
- retryDelay from RetryInfo (e.g., "0.088325827s")
|
|
566
|
+
- quotaResetDelay from ErrorInfo metadata (e.g., "88.325827ms")
|
|
567
|
+
|
|
568
|
+
Returns the delay in seconds, or None if parsing fails.
|
|
569
|
+
"""
|
|
570
|
+
try:
|
|
571
|
+
# Read response body if not already read
|
|
572
|
+
if not response.is_stream_consumed:
|
|
573
|
+
await response.aread()
|
|
574
|
+
|
|
575
|
+
error_data = json.loads(response.content)
|
|
576
|
+
|
|
577
|
+
if not isinstance(error_data, dict):
|
|
578
|
+
return 2.0 # Default fallback
|
|
579
|
+
|
|
580
|
+
error_info = error_data.get("error", {})
|
|
581
|
+
if not isinstance(error_info, dict):
|
|
582
|
+
return 2.0
|
|
583
|
+
|
|
584
|
+
details = error_info.get("details", [])
|
|
585
|
+
if not isinstance(details, list):
|
|
586
|
+
return 2.0
|
|
587
|
+
|
|
588
|
+
# Look for RetryInfo first (most precise)
|
|
589
|
+
for detail in details:
|
|
590
|
+
if not isinstance(detail, dict):
|
|
591
|
+
continue
|
|
592
|
+
|
|
593
|
+
detail_type = detail.get("@type", "")
|
|
594
|
+
|
|
595
|
+
# Check for RetryInfo (e.g., "0.088325827s")
|
|
596
|
+
if "RetryInfo" in detail_type:
|
|
597
|
+
retry_delay = detail.get("retryDelay", "")
|
|
598
|
+
parsed = self._parse_duration(retry_delay)
|
|
599
|
+
if parsed is not None:
|
|
600
|
+
return parsed
|
|
601
|
+
|
|
602
|
+
# Check for ErrorInfo with quotaResetDelay in metadata
|
|
603
|
+
if "ErrorInfo" in detail_type:
|
|
604
|
+
metadata = detail.get("metadata", {})
|
|
605
|
+
if isinstance(metadata, dict):
|
|
606
|
+
quota_delay = metadata.get("quotaResetDelay", "")
|
|
607
|
+
parsed = self._parse_duration(quota_delay)
|
|
608
|
+
if parsed is not None:
|
|
609
|
+
return parsed
|
|
610
|
+
|
|
611
|
+
return 2.0 # Default if no delay found
|
|
612
|
+
|
|
613
|
+
except (json.JSONDecodeError, Exception) as e:
|
|
614
|
+
logger.debug("Failed to parse rate limit response: %s", e)
|
|
615
|
+
return 2.0 # Default fallback
|
|
616
|
+
|
|
617
|
+
def _parse_duration(self, duration_str: str) -> float | None:
|
|
618
|
+
"""Parse a duration string like '0.088s' or '88.325827ms' to seconds."""
|
|
619
|
+
if not duration_str or not isinstance(duration_str, str):
|
|
620
|
+
return None
|
|
621
|
+
|
|
622
|
+
duration_str = duration_str.strip()
|
|
623
|
+
|
|
624
|
+
try:
|
|
625
|
+
# Handle milliseconds (e.g., "88.325827ms")
|
|
626
|
+
if duration_str.endswith("ms"):
|
|
627
|
+
return float(duration_str[:-2]) / 1000.0
|
|
628
|
+
|
|
629
|
+
# Handle seconds (e.g., "0.088325827s")
|
|
630
|
+
if duration_str.endswith("s"):
|
|
631
|
+
return float(duration_str[:-1])
|
|
632
|
+
|
|
633
|
+
# Try parsing as raw number (assume seconds)
|
|
634
|
+
return float(duration_str)
|
|
635
|
+
|
|
636
|
+
except ValueError:
|
|
637
|
+
return None
|
|
638
|
+
|
|
570
639
|
|
|
571
640
|
def create_antigravity_client(
|
|
572
641
|
access_token: str,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
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.335 → code_puppy-0.0.336}/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.335 → code_puppy-0.0.336}/code_puppy/command_line/mcp/catalog_server_installer.py
RENAMED
|
File without changes
|
|
File without changes
|
{code_puppy-0.0.335 → code_puppy-0.0.336}/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
|