code-puppy 0.0.339__tar.gz → 0.0.340__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.
Files changed (182) hide show
  1. {code_puppy-0.0.339 → code_puppy-0.0.340}/PKG-INFO +1 -1
  2. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/claude_cache_client.py +76 -18
  3. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/cli_runner.py +6 -2
  4. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/mcp_/managed_server.py +7 -11
  5. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/tools/common.py +3 -9
  6. {code_puppy-0.0.339 → code_puppy-0.0.340}/pyproject.toml +1 -1
  7. {code_puppy-0.0.339 → code_puppy-0.0.340}/.gitignore +0 -0
  8. {code_puppy-0.0.339 → code_puppy-0.0.340}/LICENSE +0 -0
  9. {code_puppy-0.0.339 → code_puppy-0.0.340}/README.md +0 -0
  10. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/__init__.py +0 -0
  11. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/__main__.py +0 -0
  12. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/agents/__init__.py +0 -0
  13. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/agents/agent_c_reviewer.py +0 -0
  14. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/agents/agent_code_puppy.py +0 -0
  15. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/agents/agent_code_reviewer.py +0 -0
  16. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/agents/agent_cpp_reviewer.py +0 -0
  17. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/agents/agent_creator_agent.py +0 -0
  18. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/agents/agent_golang_reviewer.py +0 -0
  19. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/agents/agent_javascript_reviewer.py +0 -0
  20. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/agents/agent_manager.py +0 -0
  21. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/agents/agent_planning.py +0 -0
  22. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/agents/agent_python_programmer.py +0 -0
  23. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/agents/agent_python_reviewer.py +0 -0
  24. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/agents/agent_qa_expert.py +0 -0
  25. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/agents/agent_qa_kitten.py +0 -0
  26. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/agents/agent_security_auditor.py +0 -0
  27. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/agents/agent_typescript_reviewer.py +0 -0
  28. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/agents/base_agent.py +0 -0
  29. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/agents/json_agent.py +0 -0
  30. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/agents/prompt_reviewer.py +0 -0
  31. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/callbacks.py +0 -0
  32. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/chatgpt_codex_client.py +0 -0
  33. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/__init__.py +0 -0
  34. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/add_model_menu.py +0 -0
  35. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/attachments.py +0 -0
  36. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/autosave_menu.py +0 -0
  37. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/clipboard.py +0 -0
  38. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/colors_menu.py +0 -0
  39. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/command_handler.py +0 -0
  40. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/command_registry.py +0 -0
  41. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/config_commands.py +0 -0
  42. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/core_commands.py +0 -0
  43. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/diff_menu.py +0 -0
  44. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/file_path_completion.py +0 -0
  45. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/load_context_completion.py +0 -0
  46. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/mcp/__init__.py +0 -0
  47. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/mcp/add_command.py +0 -0
  48. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/mcp/base.py +0 -0
  49. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/mcp/catalog_server_installer.py +0 -0
  50. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/mcp/custom_server_form.py +0 -0
  51. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/mcp/custom_server_installer.py +0 -0
  52. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/mcp/edit_command.py +0 -0
  53. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/mcp/handler.py +0 -0
  54. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/mcp/help_command.py +0 -0
  55. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/mcp/install_command.py +0 -0
  56. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/mcp/install_menu.py +0 -0
  57. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/mcp/list_command.py +0 -0
  58. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/mcp/logs_command.py +0 -0
  59. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/mcp/remove_command.py +0 -0
  60. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/mcp/restart_command.py +0 -0
  61. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/mcp/search_command.py +0 -0
  62. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/mcp/start_all_command.py +0 -0
  63. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/mcp/start_command.py +0 -0
  64. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/mcp/status_command.py +0 -0
  65. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/mcp/stop_all_command.py +0 -0
  66. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/mcp/stop_command.py +0 -0
  67. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/mcp/test_command.py +0 -0
  68. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/mcp/utils.py +0 -0
  69. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/mcp/wizard_utils.py +0 -0
  70. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/mcp_completion.py +0 -0
  71. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/model_picker_completion.py +0 -0
  72. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/model_settings_menu.py +0 -0
  73. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/motd.py +0 -0
  74. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/onboarding_slides.py +0 -0
  75. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/onboarding_wizard.py +0 -0
  76. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/pin_command_completion.py +0 -0
  77. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/prompt_toolkit_completion.py +0 -0
  78. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/session_commands.py +0 -0
  79. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/command_line/utils.py +0 -0
  80. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/config.py +0 -0
  81. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/error_logging.py +0 -0
  82. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/gemini_code_assist.py +0 -0
  83. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/http_utils.py +0 -0
  84. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/keymap.py +0 -0
  85. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/main.py +0 -0
  86. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/mcp_/__init__.py +0 -0
  87. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/mcp_/async_lifecycle.py +0 -0
  88. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/mcp_/blocking_startup.py +0 -0
  89. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/mcp_/captured_stdio_server.py +0 -0
  90. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/mcp_/circuit_breaker.py +0 -0
  91. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/mcp_/config_wizard.py +0 -0
  92. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/mcp_/dashboard.py +0 -0
  93. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/mcp_/error_isolation.py +0 -0
  94. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/mcp_/examples/retry_example.py +0 -0
  95. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/mcp_/health_monitor.py +0 -0
  96. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/mcp_/manager.py +0 -0
  97. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/mcp_/mcp_logs.py +0 -0
  98. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/mcp_/registry.py +0 -0
  99. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/mcp_/retry_manager.py +0 -0
  100. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/mcp_/server_registry_catalog.py +0 -0
  101. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/mcp_/status_tracker.py +0 -0
  102. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/mcp_/system_tools.py +0 -0
  103. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/messaging/__init__.py +0 -0
  104. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/messaging/bus.py +0 -0
  105. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/messaging/commands.py +0 -0
  106. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/messaging/markdown_patches.py +0 -0
  107. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/messaging/message_queue.py +0 -0
  108. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/messaging/messages.py +0 -0
  109. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/messaging/queue_console.py +0 -0
  110. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/messaging/renderers.py +0 -0
  111. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/messaging/rich_renderer.py +0 -0
  112. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/messaging/spinner/__init__.py +0 -0
  113. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/messaging/spinner/console_spinner.py +0 -0
  114. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/messaging/spinner/spinner_base.py +0 -0
  115. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/model_factory.py +0 -0
  116. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/model_utils.py +0 -0
  117. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/models.json +0 -0
  118. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/models_dev_api.json +0 -0
  119. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/models_dev_parser.py +0 -0
  120. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/plugins/__init__.py +0 -0
  121. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/plugins/antigravity_oauth/__init__.py +0 -0
  122. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/plugins/antigravity_oauth/accounts.py +0 -0
  123. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/plugins/antigravity_oauth/antigravity_model.py +0 -0
  124. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/plugins/antigravity_oauth/config.py +0 -0
  125. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/plugins/antigravity_oauth/constants.py +0 -0
  126. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/plugins/antigravity_oauth/oauth.py +0 -0
  127. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/plugins/antigravity_oauth/register_callbacks.py +0 -0
  128. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/plugins/antigravity_oauth/storage.py +0 -0
  129. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/plugins/antigravity_oauth/test_plugin.py +0 -0
  130. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/plugins/antigravity_oauth/token.py +0 -0
  131. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/plugins/antigravity_oauth/transport.py +0 -0
  132. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/plugins/antigravity_oauth/utils.py +0 -0
  133. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/plugins/chatgpt_oauth/__init__.py +0 -0
  134. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/plugins/chatgpt_oauth/config.py +0 -0
  135. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/plugins/chatgpt_oauth/oauth_flow.py +0 -0
  136. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/plugins/chatgpt_oauth/register_callbacks.py +0 -0
  137. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/plugins/chatgpt_oauth/test_plugin.py +0 -0
  138. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/plugins/chatgpt_oauth/utils.py +0 -0
  139. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/plugins/claude_code_oauth/README.md +0 -0
  140. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/plugins/claude_code_oauth/SETUP.md +0 -0
  141. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/plugins/claude_code_oauth/__init__.py +0 -0
  142. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/plugins/claude_code_oauth/config.py +0 -0
  143. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/plugins/claude_code_oauth/register_callbacks.py +0 -0
  144. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/plugins/claude_code_oauth/test_plugin.py +0 -0
  145. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/plugins/claude_code_oauth/utils.py +0 -0
  146. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/plugins/customizable_commands/__init__.py +0 -0
  147. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/plugins/customizable_commands/register_callbacks.py +0 -0
  148. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/plugins/example_custom_command/README.md +0 -0
  149. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/plugins/example_custom_command/register_callbacks.py +0 -0
  150. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/plugins/file_permission_handler/__init__.py +0 -0
  151. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/plugins/file_permission_handler/register_callbacks.py +0 -0
  152. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/plugins/oauth_puppy_html.py +0 -0
  153. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/plugins/shell_safety/__init__.py +0 -0
  154. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/plugins/shell_safety/agent_shell_safety.py +0 -0
  155. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/plugins/shell_safety/command_cache.py +0 -0
  156. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/plugins/shell_safety/register_callbacks.py +0 -0
  157. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/prompts/codex_system_prompt.md +0 -0
  158. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/pydantic_patches.py +0 -0
  159. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/reopenable_async_client.py +0 -0
  160. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/round_robin_model.py +0 -0
  161. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/session_storage.py +0 -0
  162. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/status_display.py +0 -0
  163. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/summarization_agent.py +0 -0
  164. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/terminal_utils.py +0 -0
  165. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/tools/__init__.py +0 -0
  166. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/tools/agent_tools.py +0 -0
  167. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/tools/browser/__init__.py +0 -0
  168. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/tools/browser/browser_control.py +0 -0
  169. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/tools/browser/browser_interactions.py +0 -0
  170. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/tools/browser/browser_locators.py +0 -0
  171. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/tools/browser/browser_navigation.py +0 -0
  172. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/tools/browser/browser_screenshot.py +0 -0
  173. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/tools/browser/browser_scripts.py +0 -0
  174. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/tools/browser/browser_workflows.py +0 -0
  175. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/tools/browser/camoufox_manager.py +0 -0
  176. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/tools/browser/vqa_agent.py +0 -0
  177. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/tools/command_runner.py +0 -0
  178. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/tools/file_modifications.py +0 -0
  179. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/tools/file_operations.py +0 -0
  180. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/tools/tools_content.py +0 -0
  181. {code_puppy-0.0.339 → code_puppy-0.0.340}/code_puppy/uvx_detection.py +0 -0
  182. {code_puppy-0.0.339 → code_puppy-0.0.340}/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.339
3
+ Version: 0.0.340
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
@@ -10,10 +10,13 @@ serialization, avoiding httpx/Pydantic internals.
10
10
  from __future__ import annotations
11
11
 
12
12
  import json
13
+ import logging
13
14
  from typing import Any, Callable, MutableMapping
14
15
 
15
16
  import httpx
16
17
 
18
+ logger = logging.getLogger(__name__)
19
+
17
20
  try:
18
21
  from anthropic import AsyncAnthropic
19
22
  except ImportError: # pragma: no cover - optional dep
@@ -58,25 +61,44 @@ class ClaudeCacheAsyncClient(httpx.AsyncClient):
58
61
  pass
59
62
  response = await super().send(request, *args, **kwargs)
60
63
  try:
61
- if response.status_code == 401 and not request.extensions.get(
64
+ # Check for both 401 and 400 - Anthropic/Cloudflare may return 400 for auth errors
65
+ # Also check if it's a Cloudflare HTML error response
66
+ if response.status_code in (400, 401) and not request.extensions.get(
62
67
  "claude_oauth_refresh_attempted"
63
68
  ):
64
- refreshed_token = self._refresh_claude_oauth_token()
65
- if refreshed_token:
66
- await response.aclose()
67
- body_bytes = self._extract_body_bytes(request)
68
- headers = dict(request.headers)
69
- self._update_auth_headers(headers, refreshed_token)
70
- retry_request = self.build_request(
71
- method=request.method,
72
- url=request.url,
73
- headers=headers,
74
- content=body_bytes,
75
- )
76
- retry_request.extensions["claude_oauth_refresh_attempted"] = True
77
- return await super().send(retry_request, *args, **kwargs)
78
- except Exception:
79
- pass
69
+ # Determine if this is an auth error (including Cloudflare HTML errors)
70
+ is_auth_error = response.status_code == 401
71
+
72
+ if response.status_code == 400:
73
+ # Check if this is a Cloudflare HTML error
74
+ is_auth_error = self._is_cloudflare_html_error(response)
75
+ if is_auth_error:
76
+ logger.info(
77
+ "Detected Cloudflare 400 error (likely auth-related), attempting token refresh"
78
+ )
79
+
80
+ if is_auth_error:
81
+ refreshed_token = self._refresh_claude_oauth_token()
82
+ if refreshed_token:
83
+ logger.info("Token refreshed successfully, retrying request")
84
+ await response.aclose()
85
+ body_bytes = self._extract_body_bytes(request)
86
+ headers = dict(request.headers)
87
+ self._update_auth_headers(headers, refreshed_token)
88
+ retry_request = self.build_request(
89
+ method=request.method,
90
+ url=request.url,
91
+ headers=headers,
92
+ content=body_bytes,
93
+ )
94
+ retry_request.extensions["claude_oauth_refresh_attempted"] = (
95
+ True
96
+ )
97
+ return await super().send(retry_request, *args, **kwargs)
98
+ else:
99
+ logger.warning("Token refresh failed, returning original error")
100
+ except Exception as exc:
101
+ logger.debug("Error during token refresh attempt: %s", exc)
80
102
  return response
81
103
 
82
104
  @staticmethod
@@ -111,15 +133,51 @@ class ClaudeCacheAsyncClient(httpx.AsyncClient):
111
133
  else:
112
134
  headers["Authorization"] = bearer_value
113
135
 
136
+ @staticmethod
137
+ def _is_cloudflare_html_error(response: httpx.Response) -> bool:
138
+ """Check if this is a Cloudflare HTML error response.
139
+
140
+ Cloudflare often returns HTML error pages with status 400 when
141
+ there are authentication issues.
142
+ """
143
+ # Check content type
144
+ content_type = response.headers.get("content-type", "")
145
+ if "text/html" not in content_type.lower():
146
+ return False
147
+
148
+ # Check if body contains Cloudflare markers
149
+ try:
150
+ # Read response body if not already consumed
151
+ if hasattr(response, "_content") and response._content:
152
+ body = response._content.decode("utf-8", errors="ignore")
153
+ else:
154
+ # Try to read the text (this might be already consumed)
155
+ try:
156
+ body = response.text
157
+ except Exception:
158
+ return False
159
+
160
+ # Look for Cloudflare and 400 Bad Request markers
161
+ body_lower = body.lower()
162
+ return "cloudflare" in body_lower and "400 bad request" in body_lower
163
+ except Exception as exc:
164
+ logger.debug("Error checking for Cloudflare error: %s", exc)
165
+ return False
166
+
114
167
  def _refresh_claude_oauth_token(self) -> str | None:
115
168
  try:
116
169
  from code_puppy.plugins.claude_code_oauth.utils import refresh_access_token
117
170
 
171
+ logger.info("Attempting to refresh Claude Code OAuth token...")
118
172
  refreshed_token = refresh_access_token(force=True)
119
173
  if refreshed_token:
120
174
  self._update_auth_headers(self.headers, refreshed_token)
175
+ logger.info("Successfully refreshed Claude Code OAuth token")
176
+ else:
177
+ logger.warning("Token refresh returned None")
121
178
  return refreshed_token
122
- except Exception:
179
+ except Exception as exc:
180
+ logger.error("Exception during token refresh: %s", exc)
123
181
  return None
124
182
 
125
183
  @staticmethod
@@ -144,8 +144,8 @@ async def main():
144
144
  except ImportError:
145
145
  emit_system_message("🐶 Code Puppy is Loading...")
146
146
 
147
- # Check for truecolor support and warn if not available
148
- print_truecolor_warning(display_console)
147
+ # Truecolor warning moved to interactive_mode() so it prints LAST
148
+ # after all the help stuff - max visibility for the ugly red box!
149
149
 
150
150
  available_port = find_available_port()
151
151
  if available_port is None:
@@ -382,6 +382,10 @@ async def interactive_mode(message_renderer, initial_command: str = None) -> Non
382
382
 
383
383
  emit_warning(f"MOTD error: {e}")
384
384
 
385
+ # Print truecolor warning LAST so it's the most visible thing on startup
386
+ # Big ugly red box should be impossible to miss! 🔴
387
+ print_truecolor_warning(display_console)
388
+
385
389
  # Initialize the runtime agent manager
386
390
  if initial_command:
387
391
  from code_puppy.agents import get_current_agent
@@ -222,18 +222,14 @@ class ManagedMCPServer:
222
222
  http_kwargs["timeout"] = config["timeout"]
223
223
  if "read_timeout" in config:
224
224
  http_kwargs["read_timeout"] = config["read_timeout"]
225
- if "headers" in config:
226
- # Expand environment variables in headers
227
- headers = config.get("headers")
228
- resolved_headers = {}
229
- if isinstance(headers, dict):
230
- for k, v in headers.items():
231
- if isinstance(v, str):
232
- resolved_headers[k] = os.path.expandvars(v)
233
- else:
234
- resolved_headers[k] = v
235
- http_kwargs["headers"] = resolved_headers
225
+
226
+ # Handle http_client vs headers (mutually exclusive)
227
+ if "http_client" in config:
228
+ # Use provided http_client
229
+ http_kwargs["http_client"] = config["http_client"]
230
+ elif config.get("headers"):
236
231
  # Create HTTP client if headers are provided but no client specified
232
+ http_kwargs["http_client"] = self._get_http_client()
237
233
 
238
234
  self._pydantic_server = MCPServerStreamableHTTP(
239
235
  **http_kwargs, process_tool_call=process_tool_call
@@ -727,15 +727,9 @@ def _format_diff_with_syntax_highlighting(
727
727
  result.append("\n")
728
728
  continue
729
729
 
730
- # Handle diff headers specially
731
- if line.startswith("---"):
732
- result.append(line, style="yellow")
733
- elif line.startswith("+++"):
734
- result.append(line, style="yellow")
735
- elif line.startswith("@@"):
736
- result.append(line, style="cyan")
737
- elif line.startswith(("diff ", "index ")):
738
- result.append(line, style="dim")
730
+ # Skip diff headers - they're redundant noise since we show the filename in the banner
731
+ if line.startswith(("---", "+++", "@@", "diff ", "index ")):
732
+ continue
739
733
  else:
740
734
  # Determine line type and extract code content
741
735
  if line.startswith("-"):
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "code-puppy"
7
- version = "0.0.339"
7
+ version = "0.0.340"
8
8
  description = "Code generation agent"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11,<3.14"
File without changes
File without changes
File without changes