code-puppy 0.0.342__tar.gz → 0.0.344__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.342 → code_puppy-0.0.344}/PKG-INFO +1 -23
- {code_puppy-0.0.342 → code_puppy-0.0.344}/README.md +0 -21
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/agents/base_agent.py +37 -129
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/cli_runner.py +0 -35
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/config_commands.py +0 -10
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/mcp/custom_server_form.py +54 -19
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/mcp/custom_server_installer.py +2 -2
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/mcp/handler.py +0 -2
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/mcp/help_command.py +1 -5
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/mcp/start_command.py +36 -18
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/onboarding_slides.py +0 -1
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/prompt_toolkit_completion.py +26 -6
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/config.py +0 -23
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/mcp_/async_lifecycle.py +35 -4
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/mcp_/managed_server.py +46 -18
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/mcp_/manager.py +81 -52
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/summarization_agent.py +1 -11
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/tools/agent_tools.py +11 -55
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/tools/browser/vqa_agent.py +1 -7
- {code_puppy-0.0.342 → code_puppy-0.0.344}/pyproject.toml +1 -2
- code_puppy-0.0.342/code_puppy/command_line/mcp/add_command.py +0 -170
- {code_puppy-0.0.342 → code_puppy-0.0.344}/.gitignore +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/LICENSE +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/__init__.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/__main__.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/agents/__init__.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/agents/agent_c_reviewer.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/agents/agent_code_puppy.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/agents/agent_code_reviewer.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/agents/agent_cpp_reviewer.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/agents/agent_creator_agent.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/agents/agent_golang_reviewer.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/agents/agent_javascript_reviewer.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/agents/agent_manager.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/agents/agent_planning.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/agents/agent_python_programmer.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/agents/agent_python_reviewer.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/agents/agent_qa_expert.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/agents/agent_qa_kitten.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/agents/agent_security_auditor.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/agents/agent_typescript_reviewer.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/agents/json_agent.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/agents/prompt_reviewer.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/callbacks.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/chatgpt_codex_client.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/claude_cache_client.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/__init__.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/add_model_menu.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/attachments.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/autosave_menu.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/clipboard.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/colors_menu.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/command_handler.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/command_registry.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/core_commands.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/diff_menu.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/file_path_completion.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/load_context_completion.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/mcp/__init__.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/mcp/base.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/mcp/catalog_server_installer.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/mcp/edit_command.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/mcp/install_command.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/mcp/install_menu.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/mcp/list_command.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/mcp/logs_command.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/mcp/remove_command.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/mcp/restart_command.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/mcp/search_command.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/mcp/start_all_command.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/mcp/status_command.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/mcp/stop_all_command.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/mcp/stop_command.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/mcp/test_command.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/mcp/utils.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/mcp/wizard_utils.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/mcp_completion.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/model_picker_completion.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/model_settings_menu.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/motd.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/onboarding_wizard.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/pin_command_completion.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/session_commands.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/utils.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/error_logging.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/gemini_code_assist.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/http_utils.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/keymap.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/main.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/mcp_/__init__.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/mcp_/blocking_startup.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/mcp_/captured_stdio_server.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/mcp_/circuit_breaker.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/mcp_/config_wizard.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/mcp_/dashboard.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/mcp_/error_isolation.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/mcp_/examples/retry_example.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/mcp_/health_monitor.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/mcp_/mcp_logs.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/mcp_/registry.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/mcp_/retry_manager.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/mcp_/server_registry_catalog.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/mcp_/status_tracker.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/mcp_/system_tools.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/messaging/__init__.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/messaging/bus.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/messaging/commands.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/messaging/markdown_patches.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/messaging/message_queue.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/messaging/messages.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/messaging/queue_console.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/messaging/renderers.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/messaging/rich_renderer.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/messaging/spinner/__init__.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/messaging/spinner/console_spinner.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/messaging/spinner/spinner_base.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/model_factory.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/model_utils.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/models.json +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/models_dev_api.json +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/models_dev_parser.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/plugins/__init__.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/plugins/antigravity_oauth/__init__.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/plugins/antigravity_oauth/accounts.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/plugins/antigravity_oauth/antigravity_model.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/plugins/antigravity_oauth/config.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/plugins/antigravity_oauth/constants.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/plugins/antigravity_oauth/oauth.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/plugins/antigravity_oauth/register_callbacks.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/plugins/antigravity_oauth/storage.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/plugins/antigravity_oauth/test_plugin.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/plugins/antigravity_oauth/token.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/plugins/antigravity_oauth/transport.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/plugins/antigravity_oauth/utils.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/plugins/chatgpt_oauth/__init__.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/plugins/chatgpt_oauth/config.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/plugins/chatgpt_oauth/oauth_flow.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/plugins/chatgpt_oauth/register_callbacks.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/plugins/chatgpt_oauth/test_plugin.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/plugins/chatgpt_oauth/utils.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/plugins/claude_code_oauth/README.md +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/plugins/claude_code_oauth/SETUP.md +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/plugins/claude_code_oauth/__init__.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/plugins/claude_code_oauth/config.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/plugins/claude_code_oauth/register_callbacks.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/plugins/claude_code_oauth/test_plugin.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/plugins/claude_code_oauth/utils.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/plugins/customizable_commands/__init__.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/plugins/customizable_commands/register_callbacks.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/plugins/example_custom_command/README.md +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/plugins/example_custom_command/register_callbacks.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/plugins/file_permission_handler/__init__.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/plugins/file_permission_handler/register_callbacks.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/plugins/oauth_puppy_html.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/plugins/shell_safety/__init__.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/plugins/shell_safety/agent_shell_safety.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/plugins/shell_safety/command_cache.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/plugins/shell_safety/register_callbacks.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/prompts/codex_system_prompt.md +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/pydantic_patches.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/reopenable_async_client.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/round_robin_model.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/session_storage.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/status_display.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/terminal_utils.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/tools/__init__.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/tools/browser/__init__.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/tools/browser/browser_control.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/tools/browser/browser_interactions.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/tools/browser/browser_locators.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/tools/browser/browser_navigation.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/tools/browser/browser_screenshot.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/tools/browser/browser_scripts.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/tools/browser/browser_workflows.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/tools/browser/camoufox_manager.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/tools/command_runner.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/tools/common.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/tools/file_modifications.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/tools/file_operations.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/tools/tools_content.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/uvx_detection.py +0 -0
- {code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/version_checker.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: code-puppy
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.344
|
|
4
4
|
Summary: Code generation agent
|
|
5
5
|
Project-URL: repository, https://github.com/mpfaffenberger/code_puppy
|
|
6
6
|
Project-URL: HomePage, https://github.com/mpfaffenberger/code_puppy
|
|
@@ -16,7 +16,6 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
16
16
|
Classifier: Topic :: Software Development :: Code Generators
|
|
17
17
|
Requires-Python: <3.14,>=3.11
|
|
18
18
|
Requires-Dist: camoufox>=0.4.11
|
|
19
|
-
Requires-Dist: dbos>=2.5.0
|
|
20
19
|
Requires-Dist: fastapi>=0.111.0
|
|
21
20
|
Requires-Dist: httpx[http2]>=0.24.1
|
|
22
21
|
Requires-Dist: json-repair>=0.46.2
|
|
@@ -174,27 +173,6 @@ These providers are automatically configured with correct OpenAI-compatible endp
|
|
|
174
173
|
- **⚠️ Unsupported Providers** - Providers like Amazon Bedrock and Google Vertex that require special authentication are clearly marked
|
|
175
174
|
- **⚠️ No Tool Calling** - Models without tool calling support show a big warning since they can't use Code Puppy's file/shell tools
|
|
176
175
|
|
|
177
|
-
### Durable Execution
|
|
178
|
-
|
|
179
|
-
Code Puppy now supports **[DBOS](https://github.com/dbos-inc/dbos-transact-py)** durable execution.
|
|
180
|
-
|
|
181
|
-
When enabled, every agent is automatically wrapped as a `DBOSAgent`, checkpointing key interactions (including agent inputs, LLM responses, MCP calls, and tool calls) in a database for durability and recovery.
|
|
182
|
-
|
|
183
|
-
You can toggle DBOS via either of these options:
|
|
184
|
-
|
|
185
|
-
- CLI config (persists): `/set enable_dbos true` (or `false` to disable)
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
Config takes precedence if set; otherwise the environment variable is used.
|
|
189
|
-
|
|
190
|
-
### Configuration
|
|
191
|
-
|
|
192
|
-
The following environment variables control DBOS behavior:
|
|
193
|
-
- `DBOS_CONDUCTOR_KEY`: If set, Code Puppy connects to the [DBOS Management Console](https://console.dbos.dev/). Make sure you first register an app named `dbos-code-puppy` on the console to generate a Conductor key. Default: `None`.
|
|
194
|
-
- `DBOS_LOG_LEVEL`: Logging verbosity: `CRITICAL`, `ERROR`, `WARNING`, `INFO`, or `DEBUG`. Default: `ERROR`.
|
|
195
|
-
- `DBOS_SYSTEM_DATABASE_URL`: Database URL used by DBOS. Can point to a local SQLite file or a Postgres instance. Example: `postgresql://postgres:dbos@localhost:5432/postgres`. Default: `dbos_store.sqlite` file in the config directory.
|
|
196
|
-
- `DBOS_APP_VERSION`: If set, Code Puppy uses it as the [DBOS application version](https://docs.dbos.dev/architecture#application-and-workflow-versions) and automatically tries to recover pending workflows for this version. Default: Code Puppy version + Unix timestamp in millisecond (disable automatic recovery).
|
|
197
|
-
|
|
198
176
|
### Custom Commands
|
|
199
177
|
Create markdown files in `.claude/commands/`, `.github/prompts/`, or `.agents/commands/` to define custom slash commands. The filename becomes the command name and the content runs as a prompt.
|
|
200
178
|
|
|
@@ -133,27 +133,6 @@ These providers are automatically configured with correct OpenAI-compatible endp
|
|
|
133
133
|
- **⚠️ Unsupported Providers** - Providers like Amazon Bedrock and Google Vertex that require special authentication are clearly marked
|
|
134
134
|
- **⚠️ No Tool Calling** - Models without tool calling support show a big warning since they can't use Code Puppy's file/shell tools
|
|
135
135
|
|
|
136
|
-
### Durable Execution
|
|
137
|
-
|
|
138
|
-
Code Puppy now supports **[DBOS](https://github.com/dbos-inc/dbos-transact-py)** durable execution.
|
|
139
|
-
|
|
140
|
-
When enabled, every agent is automatically wrapped as a `DBOSAgent`, checkpointing key interactions (including agent inputs, LLM responses, MCP calls, and tool calls) in a database for durability and recovery.
|
|
141
|
-
|
|
142
|
-
You can toggle DBOS via either of these options:
|
|
143
|
-
|
|
144
|
-
- CLI config (persists): `/set enable_dbos true` (or `false` to disable)
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
Config takes precedence if set; otherwise the environment variable is used.
|
|
148
|
-
|
|
149
|
-
### Configuration
|
|
150
|
-
|
|
151
|
-
The following environment variables control DBOS behavior:
|
|
152
|
-
- `DBOS_CONDUCTOR_KEY`: If set, Code Puppy connects to the [DBOS Management Console](https://console.dbos.dev/). Make sure you first register an app named `dbos-code-puppy` on the console to generate a Conductor key. Default: `None`.
|
|
153
|
-
- `DBOS_LOG_LEVEL`: Logging verbosity: `CRITICAL`, `ERROR`, `WARNING`, `INFO`, or `DEBUG`. Default: `ERROR`.
|
|
154
|
-
- `DBOS_SYSTEM_DATABASE_URL`: Database URL used by DBOS. Can point to a local SQLite file or a Postgres instance. Example: `postgresql://postgres:dbos@localhost:5432/postgres`. Default: `dbos_store.sqlite` file in the config directory.
|
|
155
|
-
- `DBOS_APP_VERSION`: If set, Code Puppy uses it as the [DBOS application version](https://docs.dbos.dev/architecture#application-and-workflow-versions) and automatically tries to recover pending workflows for this version. Default: Code Puppy version + Unix timestamp in millisecond (disable automatic recovery).
|
|
156
|
-
|
|
157
136
|
### Custom Commands
|
|
158
137
|
Create markdown files in `.claude/commands/`, `.github/prompts/`, or `.agents/commands/` to define custom slash commands. The filename becomes the command name and the content runs as a prompt.
|
|
159
138
|
|
|
@@ -24,7 +24,6 @@ from typing import (
|
|
|
24
24
|
import mcp
|
|
25
25
|
import pydantic
|
|
26
26
|
import pydantic_ai.models
|
|
27
|
-
from dbos import DBOS, SetWorkflowID
|
|
28
27
|
from pydantic_ai import Agent as PydanticAgent
|
|
29
28
|
from pydantic_ai import (
|
|
30
29
|
BinaryContent,
|
|
@@ -35,7 +34,6 @@ from pydantic_ai import (
|
|
|
35
34
|
UsageLimitExceeded,
|
|
36
35
|
UsageLimits,
|
|
37
36
|
)
|
|
38
|
-
from pydantic_ai.durable_exec.dbos import DBOSAgent
|
|
39
37
|
from pydantic_ai.messages import (
|
|
40
38
|
ModelMessage,
|
|
41
39
|
ModelRequest,
|
|
@@ -56,7 +54,6 @@ from code_puppy.config import (
|
|
|
56
54
|
get_global_model_name,
|
|
57
55
|
get_message_limit,
|
|
58
56
|
get_protected_token_count,
|
|
59
|
-
get_use_dbos,
|
|
60
57
|
get_value,
|
|
61
58
|
)
|
|
62
59
|
from code_puppy.error_logging import log_error
|
|
@@ -1212,56 +1209,25 @@ class BaseAgent(ABC):
|
|
|
1212
1209
|
|
|
1213
1210
|
self._last_model_name = resolved_model_name
|
|
1214
1211
|
# expose for run_with_mcp
|
|
1215
|
-
# Wrap it with DBOS, but handle MCP servers separately to avoid serialization issues
|
|
1216
1212
|
global _reload_count
|
|
1217
1213
|
_reload_count += 1
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
# Register regular tools (non-MCP) on the new agent
|
|
1233
|
-
agent_tools = self.get_available_tools()
|
|
1234
|
-
register_tools_for_agent(agent_without_mcp, agent_tools)
|
|
1235
|
-
|
|
1236
|
-
# Wrap with DBOS
|
|
1237
|
-
dbos_agent = DBOSAgent(
|
|
1238
|
-
agent_without_mcp, name=f"{self.name}-{_reload_count}"
|
|
1239
|
-
)
|
|
1240
|
-
self.pydantic_agent = dbos_agent
|
|
1241
|
-
self._code_generation_agent = dbos_agent
|
|
1214
|
+
# Include filtered MCP servers in the agent
|
|
1215
|
+
p_agent = PydanticAgent(
|
|
1216
|
+
model=model,
|
|
1217
|
+
instructions=instructions,
|
|
1218
|
+
output_type=str,
|
|
1219
|
+
retries=3,
|
|
1220
|
+
toolsets=filtered_mcp_servers if filtered_mcp_servers else [],
|
|
1221
|
+
history_processors=[self.message_history_accumulator],
|
|
1222
|
+
model_settings=model_settings,
|
|
1223
|
+
)
|
|
1224
|
+
# Register regular tools on the agent
|
|
1225
|
+
agent_tools = self.get_available_tools()
|
|
1226
|
+
register_tools_for_agent(p_agent, agent_tools)
|
|
1242
1227
|
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
# Normal path without DBOS - include filtered MCP servers in the agent
|
|
1247
|
-
# Re-create agent with filtered MCP servers
|
|
1248
|
-
p_agent = PydanticAgent(
|
|
1249
|
-
model=model,
|
|
1250
|
-
instructions=instructions,
|
|
1251
|
-
output_type=str,
|
|
1252
|
-
retries=3,
|
|
1253
|
-
toolsets=filtered_mcp_servers,
|
|
1254
|
-
history_processors=[self.message_history_accumulator],
|
|
1255
|
-
model_settings=model_settings,
|
|
1256
|
-
)
|
|
1257
|
-
# Register regular tools on the agent
|
|
1258
|
-
agent_tools = self.get_available_tools()
|
|
1259
|
-
register_tools_for_agent(p_agent, agent_tools)
|
|
1260
|
-
|
|
1261
|
-
self.pydantic_agent = p_agent
|
|
1262
|
-
self._code_generation_agent = p_agent
|
|
1263
|
-
self._mcp_servers = filtered_mcp_servers
|
|
1264
|
-
self._mcp_servers = mcp_servers
|
|
1228
|
+
self.pydantic_agent = p_agent
|
|
1229
|
+
self._code_generation_agent = p_agent
|
|
1230
|
+
self._mcp_servers = filtered_mcp_servers
|
|
1265
1231
|
return self._code_generation_agent
|
|
1266
1232
|
|
|
1267
1233
|
def _create_agent_with_output_type(self, output_type: Type[Any]) -> PydanticAgent:
|
|
@@ -1275,7 +1241,7 @@ class BaseAgent(ABC):
|
|
|
1275
1241
|
output_type: The Pydantic model or type for structured output.
|
|
1276
1242
|
|
|
1277
1243
|
Returns:
|
|
1278
|
-
A configured PydanticAgent
|
|
1244
|
+
A configured PydanticAgent with the custom output_type.
|
|
1279
1245
|
"""
|
|
1280
1246
|
from code_puppy.model_utils import prepare_prompt_for_model
|
|
1281
1247
|
from code_puppy.tools import register_tools_for_agent
|
|
@@ -1302,38 +1268,19 @@ class BaseAgent(ABC):
|
|
|
1302
1268
|
global _reload_count
|
|
1303
1269
|
_reload_count += 1
|
|
1304
1270
|
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
dbos_agent = DBOSAgent(
|
|
1318
|
-
temp_agent, name=f"{self.name}-structured-{_reload_count}"
|
|
1319
|
-
)
|
|
1320
|
-
return dbos_agent
|
|
1321
|
-
else:
|
|
1322
|
-
temp_agent = PydanticAgent(
|
|
1323
|
-
model=model,
|
|
1324
|
-
instructions=instructions,
|
|
1325
|
-
output_type=output_type,
|
|
1326
|
-
retries=3,
|
|
1327
|
-
toolsets=mcp_servers,
|
|
1328
|
-
history_processors=[self.message_history_accumulator],
|
|
1329
|
-
model_settings=model_settings,
|
|
1330
|
-
)
|
|
1331
|
-
agent_tools = self.get_available_tools()
|
|
1332
|
-
register_tools_for_agent(temp_agent, agent_tools)
|
|
1333
|
-
return temp_agent
|
|
1271
|
+
temp_agent = PydanticAgent(
|
|
1272
|
+
model=model,
|
|
1273
|
+
instructions=instructions,
|
|
1274
|
+
output_type=output_type,
|
|
1275
|
+
retries=3,
|
|
1276
|
+
toolsets=mcp_servers,
|
|
1277
|
+
history_processors=[self.message_history_accumulator],
|
|
1278
|
+
model_settings=model_settings,
|
|
1279
|
+
)
|
|
1280
|
+
agent_tools = self.get_available_tools()
|
|
1281
|
+
register_tools_for_agent(temp_agent, agent_tools)
|
|
1282
|
+
return temp_agent
|
|
1334
1283
|
|
|
1335
|
-
# It's okay to decorate it with DBOS.step even if not using DBOS; the decorator is a no-op in that case.
|
|
1336
|
-
@DBOS.step()
|
|
1337
1284
|
def message_history_accumulator(self, ctx: RunContext, messages: List[Any]):
|
|
1338
1285
|
_message_history = self.get_message_history()
|
|
1339
1286
|
message_history_hashes = set([self.hash_message(m) for m in _message_history])
|
|
@@ -1841,49 +1788,14 @@ class BaseAgent(ABC):
|
|
|
1841
1788
|
|
|
1842
1789
|
usage_limits = UsageLimits(request_limit=get_message_limit())
|
|
1843
1790
|
|
|
1844
|
-
#
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
pydantic_agent._toolsets = original_toolsets + self._mcp_servers
|
|
1853
|
-
pydantic_agent._toolsets = original_toolsets + self._mcp_servers
|
|
1854
|
-
|
|
1855
|
-
try:
|
|
1856
|
-
# Set the workflow ID for DBOS context so DBOS and Code Puppy ID match
|
|
1857
|
-
with SetWorkflowID(group_id):
|
|
1858
|
-
result_ = await pydantic_agent.run(
|
|
1859
|
-
prompt_payload,
|
|
1860
|
-
message_history=self.get_message_history(),
|
|
1861
|
-
usage_limits=usage_limits,
|
|
1862
|
-
event_stream_handler=self._event_stream_handler,
|
|
1863
|
-
**kwargs,
|
|
1864
|
-
)
|
|
1865
|
-
finally:
|
|
1866
|
-
# Always restore original toolsets
|
|
1867
|
-
pydantic_agent._toolsets = original_toolsets
|
|
1868
|
-
elif get_use_dbos():
|
|
1869
|
-
# DBOS without MCP servers
|
|
1870
|
-
with SetWorkflowID(group_id):
|
|
1871
|
-
result_ = await pydantic_agent.run(
|
|
1872
|
-
prompt_payload,
|
|
1873
|
-
message_history=self.get_message_history(),
|
|
1874
|
-
usage_limits=usage_limits,
|
|
1875
|
-
event_stream_handler=self._event_stream_handler,
|
|
1876
|
-
**kwargs,
|
|
1877
|
-
)
|
|
1878
|
-
else:
|
|
1879
|
-
# Non-DBOS path (MCP servers are already included)
|
|
1880
|
-
result_ = await pydantic_agent.run(
|
|
1881
|
-
prompt_payload,
|
|
1882
|
-
message_history=self.get_message_history(),
|
|
1883
|
-
usage_limits=usage_limits,
|
|
1884
|
-
event_stream_handler=self._event_stream_handler,
|
|
1885
|
-
**kwargs,
|
|
1886
|
-
)
|
|
1791
|
+
# MCP servers are already included in the agent
|
|
1792
|
+
result_ = await pydantic_agent.run(
|
|
1793
|
+
prompt_payload,
|
|
1794
|
+
message_history=self.get_message_history(),
|
|
1795
|
+
usage_limits=usage_limits,
|
|
1796
|
+
event_stream_handler=self._event_stream_handler,
|
|
1797
|
+
**kwargs,
|
|
1798
|
+
)
|
|
1887
1799
|
return result_
|
|
1888
1800
|
except* UsageLimitExceeded as ule:
|
|
1889
1801
|
emit_info(f"Usage limit exceeded: {str(ule)}", group_id=group_id)
|
|
@@ -1899,12 +1811,8 @@ class BaseAgent(ABC):
|
|
|
1899
1811
|
)
|
|
1900
1812
|
except* asyncio.exceptions.CancelledError:
|
|
1901
1813
|
emit_info("Cancelled")
|
|
1902
|
-
if get_use_dbos():
|
|
1903
|
-
await DBOS.cancel_workflow_async(group_id)
|
|
1904
1814
|
except* InterruptedError as ie:
|
|
1905
1815
|
emit_info(f"Interrupted: {str(ie)}")
|
|
1906
|
-
if get_use_dbos():
|
|
1907
|
-
await DBOS.cancel_workflow_async(group_id)
|
|
1908
1816
|
except* Exception as other_error:
|
|
1909
1817
|
# Filter out CancelledError and UsageLimitExceeded from the exception group - let it propagate
|
|
1910
1818
|
remaining_exceptions = []
|
|
@@ -12,11 +12,9 @@ import argparse
|
|
|
12
12
|
import asyncio
|
|
13
13
|
import os
|
|
14
14
|
import sys
|
|
15
|
-
import time
|
|
16
15
|
import traceback
|
|
17
16
|
from pathlib import Path
|
|
18
17
|
|
|
19
|
-
from dbos import DBOS, DBOSConfig
|
|
20
18
|
from rich.console import Console
|
|
21
19
|
|
|
22
20
|
from code_puppy import __version__, callbacks, plugins
|
|
@@ -26,10 +24,8 @@ from code_puppy.command_line.clipboard import get_clipboard_manager
|
|
|
26
24
|
from code_puppy.config import (
|
|
27
25
|
AUTOSAVE_DIR,
|
|
28
26
|
COMMAND_HISTORY_FILE,
|
|
29
|
-
DBOS_DATABASE_URL,
|
|
30
27
|
ensure_config_exists,
|
|
31
28
|
finalize_autosave_session,
|
|
32
|
-
get_use_dbos,
|
|
33
29
|
initialize_command_history_file,
|
|
34
30
|
save_command_to_history,
|
|
35
31
|
)
|
|
@@ -287,33 +283,6 @@ async def main():
|
|
|
287
283
|
|
|
288
284
|
await callbacks.on_startup()
|
|
289
285
|
|
|
290
|
-
# Initialize DBOS if not disabled
|
|
291
|
-
if get_use_dbos():
|
|
292
|
-
# Append a Unix timestamp in ms to the version for uniqueness
|
|
293
|
-
dbos_app_version = os.environ.get(
|
|
294
|
-
"DBOS_APP_VERSION", f"{current_version}-{int(time.time() * 1000)}"
|
|
295
|
-
)
|
|
296
|
-
dbos_config: DBOSConfig = {
|
|
297
|
-
"name": "dbos-code-puppy",
|
|
298
|
-
"system_database_url": DBOS_DATABASE_URL,
|
|
299
|
-
"run_admin_server": False,
|
|
300
|
-
"conductor_key": os.environ.get(
|
|
301
|
-
"DBOS_CONDUCTOR_KEY"
|
|
302
|
-
), # Optional, if set in env, connect to conductor
|
|
303
|
-
"log_level": os.environ.get(
|
|
304
|
-
"DBOS_LOG_LEVEL", "ERROR"
|
|
305
|
-
), # Default to ERROR level to suppress verbose logs
|
|
306
|
-
"application_version": dbos_app_version, # Match DBOS app version to Code Puppy version
|
|
307
|
-
}
|
|
308
|
-
try:
|
|
309
|
-
DBOS(config=dbos_config)
|
|
310
|
-
DBOS.launch()
|
|
311
|
-
except Exception as e:
|
|
312
|
-
emit_error(f"Error initializing DBOS: {e}")
|
|
313
|
-
sys.exit(1)
|
|
314
|
-
else:
|
|
315
|
-
pass
|
|
316
|
-
|
|
317
286
|
global shutdown_flag
|
|
318
287
|
shutdown_flag = False
|
|
319
288
|
try:
|
|
@@ -338,8 +307,6 @@ async def main():
|
|
|
338
307
|
if bus_renderer:
|
|
339
308
|
bus_renderer.stop()
|
|
340
309
|
await callbacks.on_shutdown()
|
|
341
|
-
if get_use_dbos():
|
|
342
|
-
DBOS.destroy()
|
|
343
310
|
|
|
344
311
|
|
|
345
312
|
async def interactive_mode(message_renderer, initial_command: str = None) -> None:
|
|
@@ -907,8 +874,6 @@ def main_entry():
|
|
|
907
874
|
except KeyboardInterrupt:
|
|
908
875
|
# Note: Using sys.stderr for crash output - messaging system may not be available
|
|
909
876
|
sys.stderr.write(traceback.format_exc())
|
|
910
|
-
if get_use_dbos():
|
|
911
|
-
DBOS.destroy()
|
|
912
877
|
return 0
|
|
913
878
|
finally:
|
|
914
879
|
# Reset terminal on Unix-like systems (not Windows)
|
|
@@ -43,7 +43,6 @@ def handle_show_command(command: str) -> bool:
|
|
|
43
43
|
get_protected_token_count,
|
|
44
44
|
get_puppy_name,
|
|
45
45
|
get_temperature,
|
|
46
|
-
get_use_dbos,
|
|
47
46
|
get_yolo_mode,
|
|
48
47
|
)
|
|
49
48
|
from code_puppy.keymap import get_cancel_agent_display_name
|
|
@@ -72,7 +71,6 @@ def handle_show_command(command: str) -> bool:
|
|
|
72
71
|
[bold]default_agent:[/bold] [cyan]{default_agent}[/cyan]
|
|
73
72
|
[bold]model:[/bold] [green]{model}[/green]
|
|
74
73
|
[bold]YOLO_MODE:[/bold] {"[red]ON[/red]" if yolo_mode else "[yellow]off[/yellow]"}
|
|
75
|
-
[bold]DBOS:[/bold] {"[green]enabled[/green]" if get_use_dbos() else "[yellow]disabled[/yellow]"} (toggle: /set enable_dbos true|false)
|
|
76
74
|
[bold]auto_save_session:[/bold] {"[green]enabled[/green]" if auto_save else "[yellow]disabled[/yellow]"}
|
|
77
75
|
[bold]protected_tokens:[/bold] [cyan]{protected_tokens:,}[/cyan] recent tokens preserved
|
|
78
76
|
[bold]compaction_threshold:[/bold] [cyan]{compaction_threshold:.1%}[/cyan] context usage triggers compaction
|
|
@@ -213,14 +211,6 @@ def handle_set_command(command: str) -> bool:
|
|
|
213
211
|
)
|
|
214
212
|
return True
|
|
215
213
|
if key:
|
|
216
|
-
# Check if we're toggling DBOS enablement
|
|
217
|
-
if key == "enable_dbos":
|
|
218
|
-
emit_info(
|
|
219
|
-
Text.from_markup(
|
|
220
|
-
"[yellow]⚠️ DBOS configuration changed. Please restart Code Puppy for this change to take effect.[/yellow]"
|
|
221
|
-
)
|
|
222
|
-
)
|
|
223
|
-
|
|
224
214
|
# Validate cancel_agent_key before setting
|
|
225
215
|
if key == "cancel_agent_key":
|
|
226
216
|
from code_puppy.keymap import VALID_CANCEL_KEYS
|
|
@@ -43,7 +43,7 @@ CUSTOM_SERVER_EXAMPLES = {
|
|
|
43
43
|
"type": "http",
|
|
44
44
|
"url": "http://localhost:8080/mcp",
|
|
45
45
|
"headers": {
|
|
46
|
-
"Authorization": "Bearer
|
|
46
|
+
"Authorization": "Bearer $MY_API_KEY",
|
|
47
47
|
"Content-Type": "application/json"
|
|
48
48
|
},
|
|
49
49
|
"timeout": 30
|
|
@@ -52,7 +52,7 @@ CUSTOM_SERVER_EXAMPLES = {
|
|
|
52
52
|
"type": "sse",
|
|
53
53
|
"url": "http://localhost:8080/sse",
|
|
54
54
|
"headers": {
|
|
55
|
-
"Authorization": "Bearer
|
|
55
|
+
"Authorization": "Bearer $MY_API_KEY"
|
|
56
56
|
}
|
|
57
57
|
}""",
|
|
58
58
|
}
|
|
@@ -367,24 +367,59 @@ class CustomServerForm:
|
|
|
367
367
|
config_dict = json.loads(self.json_config)
|
|
368
368
|
|
|
369
369
|
try:
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
370
|
+
# In edit mode, find the existing server and update it
|
|
371
|
+
if self.edit_mode and self.original_name:
|
|
372
|
+
existing_config = self.manager.get_server_by_name(self.original_name)
|
|
373
|
+
if existing_config:
|
|
374
|
+
# Use the existing server's ID for the update
|
|
375
|
+
server_config = ServerConfig(
|
|
376
|
+
id=existing_config.id,
|
|
377
|
+
name=server_name,
|
|
378
|
+
type=server_type,
|
|
379
|
+
enabled=True,
|
|
380
|
+
config=config_dict,
|
|
381
|
+
)
|
|
382
|
+
|
|
383
|
+
# Update the server in the manager
|
|
384
|
+
success = self.manager.update_server(
|
|
385
|
+
existing_config.id, server_config
|
|
386
|
+
)
|
|
387
|
+
|
|
388
|
+
if not success:
|
|
389
|
+
self.validation_error = "Failed to update server"
|
|
390
|
+
self.status_message = "Save failed: Could not update server"
|
|
391
|
+
self.status_is_error = True
|
|
392
|
+
return False
|
|
393
|
+
|
|
394
|
+
server_id = existing_config.id
|
|
395
|
+
else:
|
|
396
|
+
# Original server not found, treat as new registration
|
|
397
|
+
server_config = ServerConfig(
|
|
398
|
+
id=server_name,
|
|
399
|
+
name=server_name,
|
|
400
|
+
type=server_type,
|
|
401
|
+
enabled=True,
|
|
402
|
+
config=config_dict,
|
|
403
|
+
)
|
|
404
|
+
server_id = self.manager.register_server(server_config)
|
|
405
|
+
else:
|
|
406
|
+
# New server - register it
|
|
407
|
+
server_config = ServerConfig(
|
|
408
|
+
id=server_name,
|
|
409
|
+
name=server_name,
|
|
410
|
+
type=server_type,
|
|
411
|
+
enabled=True,
|
|
412
|
+
config=config_dict,
|
|
385
413
|
)
|
|
386
|
-
|
|
387
|
-
|
|
414
|
+
|
|
415
|
+
# Register with manager
|
|
416
|
+
server_id = self.manager.register_server(server_config)
|
|
417
|
+
|
|
418
|
+
if not server_id:
|
|
419
|
+
self.validation_error = "Failed to register server"
|
|
420
|
+
self.status_message = "Save failed: Could not register server (name may already exist)"
|
|
421
|
+
self.status_is_error = True
|
|
422
|
+
return False
|
|
388
423
|
|
|
389
424
|
# Save to mcp_servers.json for persistence
|
|
390
425
|
if os.path.exists(MCP_SERVERS_FILE):
|
{code_puppy-0.0.342 → code_puppy-0.0.344}/code_puppy/command_line/mcp/custom_server_installer.py
RENAMED
|
@@ -24,7 +24,7 @@ CUSTOM_SERVER_EXAMPLES = {
|
|
|
24
24
|
"type": "http",
|
|
25
25
|
"url": "http://localhost:8080/mcp",
|
|
26
26
|
"headers": {
|
|
27
|
-
"Authorization": "Bearer
|
|
27
|
+
"Authorization": "Bearer $MY_API_KEY",
|
|
28
28
|
"Content-Type": "application/json"
|
|
29
29
|
},
|
|
30
30
|
"timeout": 30
|
|
@@ -33,7 +33,7 @@ CUSTOM_SERVER_EXAMPLES = {
|
|
|
33
33
|
"type": "sse",
|
|
34
34
|
"url": "http://localhost:8080/sse",
|
|
35
35
|
"headers": {
|
|
36
|
-
"Authorization": "Bearer
|
|
36
|
+
"Authorization": "Bearer $MY_API_KEY"
|
|
37
37
|
}
|
|
38
38
|
}""",
|
|
39
39
|
}
|
|
@@ -12,7 +12,6 @@ from rich.text import Text
|
|
|
12
12
|
|
|
13
13
|
from code_puppy.messaging import emit_info
|
|
14
14
|
|
|
15
|
-
from .add_command import AddCommand
|
|
16
15
|
from .base import MCPCommandBase
|
|
17
16
|
from .edit_command import EditCommand
|
|
18
17
|
from .help_command import HelpCommand
|
|
@@ -63,7 +62,6 @@ class MCPCommandHandler(MCPCommandBase):
|
|
|
63
62
|
"restart": RestartCommand(),
|
|
64
63
|
"status": StatusCommand(),
|
|
65
64
|
"test": TestCommand(),
|
|
66
|
-
"add": AddCommand(),
|
|
67
65
|
"edit": EditCommand(),
|
|
68
66
|
"remove": RemoveCommand(),
|
|
69
67
|
"logs": LogsCommand(),
|
|
@@ -101,10 +101,6 @@ class HelpCommand(MCPCommandBase):
|
|
|
101
101
|
Text("/mcp logs", style="cyan")
|
|
102
102
|
+ Text(" <name> [limit] Show recent events (default limit: 10)")
|
|
103
103
|
)
|
|
104
|
-
help_lines.append(
|
|
105
|
-
Text("/mcp add", style="cyan")
|
|
106
|
-
+ Text(" [json] Add new server (JSON or wizard)")
|
|
107
|
-
)
|
|
108
104
|
help_lines.append(
|
|
109
105
|
Text("/mcp edit", style="cyan")
|
|
110
106
|
+ Text(" <name> Edit existing server config")
|
|
@@ -134,7 +130,7 @@ class HelpCommand(MCPCommandBase):
|
|
|
134
130
|
/mcp start-all # Start all servers at once
|
|
135
131
|
/mcp stop-all # Stop all running servers
|
|
136
132
|
/mcp edit filesystem # Edit an existing server config
|
|
137
|
-
/mcp
|
|
133
|
+
/mcp remove filesystem # Remove a server"""
|
|
138
134
|
help_lines.append(Text(examples_text, style="dim"))
|
|
139
135
|
|
|
140
136
|
# Combine all lines
|
|
@@ -3,7 +3,6 @@ MCP Start Command - Starts a specific MCP server.
|
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
5
|
import logging
|
|
6
|
-
import time
|
|
7
6
|
from typing import List, Optional
|
|
8
7
|
|
|
9
8
|
from rich.text import Text
|
|
@@ -23,6 +22,7 @@ class StartCommand(MCPCommandBase):
|
|
|
23
22
|
Command handler for starting MCP servers.
|
|
24
23
|
|
|
25
24
|
Starts a specific MCP server by name and reloads the agent.
|
|
25
|
+
The server subprocess starts asynchronously in the background.
|
|
26
26
|
"""
|
|
27
27
|
|
|
28
28
|
def execute(self, args: List[str], group_id: Optional[str] = None) -> None:
|
|
@@ -56,31 +56,49 @@ class StartCommand(MCPCommandBase):
|
|
|
56
56
|
suggest_similar_servers(self.manager, server_name, group_id=group_id)
|
|
57
57
|
return
|
|
58
58
|
|
|
59
|
-
#
|
|
59
|
+
# Get server info for better messaging (safely handle missing method)
|
|
60
|
+
server_type = "unknown"
|
|
61
|
+
try:
|
|
62
|
+
if hasattr(self.manager, "get_server_by_name"):
|
|
63
|
+
server_config = self.manager.get_server_by_name(server_name)
|
|
64
|
+
server_type = (
|
|
65
|
+
getattr(server_config, "type", "unknown")
|
|
66
|
+
if server_config
|
|
67
|
+
else "unknown"
|
|
68
|
+
)
|
|
69
|
+
except Exception:
|
|
70
|
+
pass # Default to unknown type if we can't determine it
|
|
71
|
+
|
|
72
|
+
# Start the server (schedules async start in background)
|
|
60
73
|
success = self.manager.start_server_sync(server_id)
|
|
61
74
|
|
|
62
75
|
if success:
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
76
|
+
if server_type == "stdio":
|
|
77
|
+
# Stdio servers start subprocess asynchronously
|
|
78
|
+
emit_success(
|
|
79
|
+
f"🚀 Starting server: {server_name} (subprocess starting in background)",
|
|
80
|
+
message_group=group_id,
|
|
81
|
+
)
|
|
82
|
+
emit_info(
|
|
83
|
+
Text.from_markup(
|
|
84
|
+
"[dim]Tip: Use /mcp status to check if the server is fully initialized[/dim]"
|
|
85
|
+
),
|
|
86
|
+
message_group=group_id,
|
|
87
|
+
)
|
|
88
|
+
else:
|
|
89
|
+
# SSE/HTTP servers connect on first use
|
|
90
|
+
emit_success(
|
|
91
|
+
f"✅ Enabled server: {server_name}",
|
|
92
|
+
message_group=group_id,
|
|
93
|
+
)
|
|
78
94
|
|
|
79
95
|
# Reload the agent to pick up the newly enabled server
|
|
96
|
+
# NOTE: We don't block or wait - the server will be ready
|
|
97
|
+
# when the next prompt runs (pydantic-ai handles connection)
|
|
80
98
|
try:
|
|
81
99
|
agent = get_current_agent()
|
|
82
100
|
agent.reload_code_generation_agent()
|
|
83
|
-
#
|
|
101
|
+
# Clear MCP tool cache - it will be repopulated on next run
|
|
84
102
|
agent.update_mcp_tool_cache_sync()
|
|
85
103
|
emit_info(
|
|
86
104
|
"Agent reloaded with updated servers",
|
|
@@ -122,7 +122,6 @@ def slide_mcp() -> str:
|
|
|
122
122
|
content += "[white]Supercharge with external tools![/white]\n\n"
|
|
123
123
|
content += "[green]Commands:[/green]\n"
|
|
124
124
|
content += " [cyan]/mcp install[/cyan] Browse catalog\n"
|
|
125
|
-
content += " [cyan]/mcp add[/cyan] Add custom server\n"
|
|
126
125
|
content += " [cyan]/mcp list[/cyan] See your servers\n\n"
|
|
127
126
|
content += "[yellow]🌟 Popular picks:[/yellow]\n"
|
|
128
127
|
content += " • GitHub integration\n"
|