code-puppy 0.0.802__tar.gz → 0.0.804__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 (278) hide show
  1. {code_puppy-0.0.802 → code_puppy-0.0.804}/PKG-INFO +1 -1
  2. code_puppy-0.0.804/code_puppy/_pydantic_tool_helpers.py +103 -0
  3. code_puppy-0.0.804/code_puppy/private_inference.py +114 -0
  4. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/pydantic_patches.py +30 -127
  5. {code_puppy-0.0.802 → code_puppy-0.0.804}/pyproject.toml +1 -1
  6. {code_puppy-0.0.802 → code_puppy-0.0.804}/.gitignore +0 -0
  7. {code_puppy-0.0.802 → code_puppy-0.0.804}/LICENSE +0 -0
  8. {code_puppy-0.0.802 → code_puppy-0.0.804}/README.md +0 -0
  9. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/__init__.py +0 -0
  10. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/__main__.py +0 -0
  11. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/agent_execution_context.py +0 -0
  12. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/agents/__init__.py +0 -0
  13. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/agents/_builder.py +0 -0
  14. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/agents/_compaction.py +0 -0
  15. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/agents/_diagnostics.py +0 -0
  16. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/agents/_history.py +0 -0
  17. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/agents/_key_listeners.py +0 -0
  18. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/agents/_model_message_transform.py +0 -0
  19. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/agents/_non_streaming_render.py +0 -0
  20. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/agents/_output_limits.py +0 -0
  21. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/agents/_run_signals.py +0 -0
  22. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/agents/_runtime.py +0 -0
  23. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/agents/_steer_processor.py +0 -0
  24. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/agents/_subagent_recursion.py +0 -0
  25. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/agents/agent_code_puppy.py +0 -0
  26. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/agents/agent_creator_agent.py +0 -0
  27. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/agents/agent_helios.py +0 -0
  28. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/agents/agent_manager.py +0 -0
  29. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/agents/agent_model_judge.py +0 -0
  30. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/agents/agent_planning.py +0 -0
  31. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/agents/agent_qa_kitten.py +0 -0
  32. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/agents/agent_web_retriever.py +0 -0
  33. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/agents/base_agent.py +0 -0
  34. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/agents/event_stream_handler.py +0 -0
  35. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/agents/json_agent.py +0 -0
  36. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/agents/retry_profiles.py +0 -0
  37. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/agents/run_stats.py +0 -0
  38. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/agents/smooth_stream.py +0 -0
  39. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/agents/subagent_stream_handler.py +0 -0
  40. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/atomic_io.py +0 -0
  41. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/atomic_json.py +0 -0
  42. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/callbacks.py +0 -0
  43. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/chatgpt_codex_client.py +0 -0
  44. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/claude_cache_client.py +0 -0
  45. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/cli_runner.py +0 -0
  46. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/__init__.py +0 -0
  47. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/add_model_details.py +0 -0
  48. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/add_model_menu.py +0 -0
  49. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/agent_menu.py +0 -0
  50. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/attachments.py +0 -0
  51. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/autosave_menu.py +0 -0
  52. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/autosave_search.py +0 -0
  53. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/clipboard.py +0 -0
  54. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/colors_menu.py +0 -0
  55. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/command_handler.py +0 -0
  56. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/command_registry.py +0 -0
  57. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/completers.py +0 -0
  58. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/completion_cache.py +0 -0
  59. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/config_apply.py +0 -0
  60. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/config_commands.py +0 -0
  61. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/core_commands.py +0 -0
  62. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/file_index.py +0 -0
  63. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/file_path_completion.py +0 -0
  64. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/help_catalog.py +0 -0
  65. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/help_overlay.py +0 -0
  66. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/image_utils.py +0 -0
  67. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/load_context_completion.py +0 -0
  68. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/mcp/__init__.py +0 -0
  69. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/mcp/base.py +0 -0
  70. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/mcp/catalog_server_installer.py +0 -0
  71. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/mcp/custom_server_form.py +0 -0
  72. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/mcp/custom_server_installer.py +0 -0
  73. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/mcp/edit_command.py +0 -0
  74. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/mcp/handler.py +0 -0
  75. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/mcp/help_command.py +0 -0
  76. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/mcp/install_command.py +0 -0
  77. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/mcp/install_menu.py +0 -0
  78. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/mcp/list_command.py +0 -0
  79. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/mcp/logs_command.py +0 -0
  80. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/mcp/mcp_servers_store.py +0 -0
  81. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/mcp/remove_command.py +0 -0
  82. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/mcp/restart_command.py +0 -0
  83. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/mcp/search_command.py +0 -0
  84. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/mcp/silence_warning_command.py +0 -0
  85. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/mcp/start_all_command.py +0 -0
  86. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/mcp/start_command.py +0 -0
  87. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/mcp/status_command.py +0 -0
  88. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/mcp/stop_all_command.py +0 -0
  89. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/mcp/stop_command.py +0 -0
  90. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/mcp/trust_command.py +0 -0
  91. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/mcp/utils.py +0 -0
  92. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/mcp/wizard_utils.py +0 -0
  93. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/mcp_binding_menu.py +0 -0
  94. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/mcp_completion.py +0 -0
  95. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/menu_session.py +0 -0
  96. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/model_picker_completion.py +0 -0
  97. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/model_settings_defs.py +0 -0
  98. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/model_settings_menu.py +0 -0
  99. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/onboarding_slides.py +0 -0
  100. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/onboarding_wizard.py +0 -0
  101. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/pagination.py +0 -0
  102. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/pin_command_completion.py +0 -0
  103. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/session_browser.py +0 -0
  104. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/session_browser_data.py +0 -0
  105. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/session_commands.py +0 -0
  106. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/set_menu.py +0 -0
  107. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/set_menu_catalog.py +0 -0
  108. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/set_menu_schema.py +0 -0
  109. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/set_menu_settings.py +0 -0
  110. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/set_menu_shims.py +0 -0
  111. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/set_menu_values.py +0 -0
  112. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/shell_passthrough.py +0 -0
  113. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/skills_completion.py +0 -0
  114. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/tui_style.py +0 -0
  115. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/uc_menu.py +0 -0
  116. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/command_line/utils.py +0 -0
  117. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/config.py +0 -0
  118. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/config_file.py +0 -0
  119. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/diagnostics.py +0 -0
  120. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/error_logging.py +0 -0
  121. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/gemini_code_assist.py +0 -0
  122. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/gemini_model.py +0 -0
  123. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/hook_engine/README.md +0 -0
  124. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/hook_engine/__init__.py +0 -0
  125. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/hook_engine/aliases.py +0 -0
  126. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/hook_engine/engine.py +0 -0
  127. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/hook_engine/executor.py +0 -0
  128. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/hook_engine/matcher.py +0 -0
  129. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/hook_engine/models.py +0 -0
  130. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/hook_engine/registry.py +0 -0
  131. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/hook_engine/validator.py +0 -0
  132. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/http_retry.py +0 -0
  133. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/http_utils.py +0 -0
  134. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/httpx2_utils.py +0 -0
  135. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/i18n/__init__.py +0 -0
  136. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/i18n/audit.py +0 -0
  137. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/i18n/catalog.py +0 -0
  138. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/i18n/formats.py +0 -0
  139. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/i18n/locale.py +0 -0
  140. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/i18n/locales/en-US.json +0 -0
  141. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/i18n/locales/es.json +0 -0
  142. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/i18n/locales/fr-CA.json +0 -0
  143. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/i18n/plurals.py +0 -0
  144. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/i18n/pseudo.py +0 -0
  145. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/i18n/translate.py +0 -0
  146. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/kennel_provider.py +0 -0
  147. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/keymap.py +0 -0
  148. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/list_filtering.py +0 -0
  149. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/main.py +0 -0
  150. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/mcp_/__init__.py +0 -0
  151. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/mcp_/agent_bindings.py +0 -0
  152. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/mcp_/async_lifecycle.py +0 -0
  153. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/mcp_/blocking_startup.py +0 -0
  154. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/mcp_/circuit_breaker.py +0 -0
  155. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/mcp_/config_wizard.py +0 -0
  156. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/mcp_/dashboard.py +0 -0
  157. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/mcp_/error_isolation.py +0 -0
  158. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/mcp_/examples/retry_example.py +0 -0
  159. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/mcp_/health_monitor.py +0 -0
  160. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/mcp_/managed_server.py +0 -0
  161. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/mcp_/manager.py +0 -0
  162. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/mcp_/mcp_logs.py +0 -0
  163. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/mcp_/project_config.py +0 -0
  164. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/mcp_/registry.py +0 -0
  165. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/mcp_/retry_manager.py +0 -0
  166. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/mcp_/server_registry_catalog.py +0 -0
  167. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/mcp_/status_tracker.py +0 -0
  168. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/mcp_/system_tools.py +0 -0
  169. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/mcp_/tool_arg_coercion.py +0 -0
  170. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/mcp_/toolset_utils.py +0 -0
  171. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/mcp_prompts/__init__.py +0 -0
  172. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/mcp_prompts/hook_creator.py +0 -0
  173. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/messaging/__init__.py +0 -0
  174. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/messaging/bar_painters.py +0 -0
  175. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/messaging/bar_rendering.py +0 -0
  176. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/messaging/bottom_bar.py +0 -0
  177. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/messaging/bus.py +0 -0
  178. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/messaging/chords.py +0 -0
  179. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/messaging/commands.py +0 -0
  180. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/messaging/editor_actions.py +0 -0
  181. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/messaging/editor_completion.py +0 -0
  182. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/messaging/editor_display.py +0 -0
  183. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/messaging/editor_history.py +0 -0
  184. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/messaging/editor_keys.py +0 -0
  185. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/messaging/editor_paste.py +0 -0
  186. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/messaging/external_editor.py +0 -0
  187. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/messaging/inline_bar.py +0 -0
  188. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/messaging/line_editor.py +0 -0
  189. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/messaging/markdown_patches.py +0 -0
  190. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/messaging/message_queue.py +0 -0
  191. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/messaging/messages.py +0 -0
  192. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/messaging/pause_controller.py +0 -0
  193. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/messaging/prompt_prefix_style.py +0 -0
  194. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/messaging/queue_console.py +0 -0
  195. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/messaging/renderers.py +0 -0
  196. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/messaging/rich_renderer.py +0 -0
  197. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/messaging/run_ui.py +0 -0
  198. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/messaging/run_ui_wiring.py +0 -0
  199. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/messaging/spinner/__init__.py +0 -0
  200. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/messaging/subagent_console.py +0 -0
  201. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/messaging/transcript_guard.py +0 -0
  202. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/model_descriptions.py +0 -0
  203. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/model_factory.py +0 -0
  204. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/model_switching.py +0 -0
  205. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/model_utils.py +0 -0
  206. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/models.json +0 -0
  207. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/models_dev_api.json +0 -0
  208. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/models_dev_parser.py +0 -0
  209. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/observability.py +0 -0
  210. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/platform_utils.py +0 -0
  211. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/plugins/__init__.py +0 -0
  212. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/plugins/config.py +0 -0
  213. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/plugins/oauth_pasteback.py +0 -0
  214. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/plugins/oauth_puppy_html.py +0 -0
  215. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/plugins/trust.py +0 -0
  216. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/plugins/trust_notice.py +0 -0
  217. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/provider_credentials.py +0 -0
  218. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/provider_identity.py +0 -0
  219. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/reopenable_async_client.py +0 -0
  220. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/round_robin_model.py +0 -0
  221. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/secret_store.py +0 -0
  222. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/secret_store_backends.py +0 -0
  223. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/session_format_migration.py +0 -0
  224. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/session_lifecycle.py +0 -0
  225. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/session_migration.py +0 -0
  226. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/session_storage.py +0 -0
  227. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/session_surrogate_unpickler.py +0 -0
  228. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/skill_provider.py +0 -0
  229. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/splash.py +0 -0
  230. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/status_display.py +0 -0
  231. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/terminal_utils.py +0 -0
  232. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/token_usage.py +0 -0
  233. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/tools/__init__.py +0 -0
  234. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/tools/agent_tools.py +0 -0
  235. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/tools/apply_patch.py +0 -0
  236. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/tools/ask_user_question/__init__.py +0 -0
  237. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/tools/ask_user_question/constants.py +0 -0
  238. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/tools/ask_user_question/demo_tui.py +0 -0
  239. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/tools/ask_user_question/handler.py +0 -0
  240. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/tools/ask_user_question/models.py +0 -0
  241. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/tools/ask_user_question/registration.py +0 -0
  242. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/tools/ask_user_question/renderers.py +0 -0
  243. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/tools/ask_user_question/terminal_ui.py +0 -0
  244. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/tools/ask_user_question/theme.py +0 -0
  245. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/tools/ask_user_question/tui_loop.py +0 -0
  246. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/tools/browser/__init__.py +0 -0
  247. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/tools/browser/browser_control.py +0 -0
  248. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/tools/browser/browser_interactions.py +0 -0
  249. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/tools/browser/browser_locator_resolver.py +0 -0
  250. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/tools/browser/browser_locators.py +0 -0
  251. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/tools/browser/browser_manager.py +0 -0
  252. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/tools/browser/browser_navigation.py +0 -0
  253. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/tools/browser/browser_page_snapshot.py +0 -0
  254. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/tools/browser/browser_screenshot.py +0 -0
  255. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/tools/browser/browser_scripts.py +0 -0
  256. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/tools/browser/browser_semantic_interactions.py +0 -0
  257. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/tools/browser/browser_workflows.py +0 -0
  258. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/tools/browser/tool_registry.py +0 -0
  259. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/tools/command_runner.py +0 -0
  260. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/tools/common.py +0 -0
  261. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/tools/display.py +0 -0
  262. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/tools/file_modifications.py +0 -0
  263. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/tools/file_operations.py +0 -0
  264. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/tools/file_permission_state.py +0 -0
  265. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/tools/fs_access.py +0 -0
  266. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/tools/image_tools.py +0 -0
  267. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/tools/io_backends.py +0 -0
  268. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/tools/model_tools.py +0 -0
  269. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/tools/shell_backgrounding.py +0 -0
  270. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/tools/skills_tools.py +0 -0
  271. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/tools/subagent_context.py +0 -0
  272. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/tools/subagent_invocation.py +0 -0
  273. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/tools/subagent_usage_metrics.py +0 -0
  274. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/tools/tools_content.py +0 -0
  275. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/tools/universal_constructor.py +0 -0
  276. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/undo_manager.py +0 -0
  277. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/universal_constructor_provider.py +0 -0
  278. {code_puppy-0.0.802 → code_puppy-0.0.804}/code_puppy/version_checker.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: code-puppy
3
- Version: 0.0.802
3
+ Version: 0.0.804
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
@@ -0,0 +1,103 @@
1
+ """Small, dependency-light helpers for Code Puppy's pydantic-ai tool patch."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+
7
+ _CLAUDE_CODE_TOOL_PREFIX = "cp_"
8
+ _CLAUDE_CODE_MODEL_PREFIX = "claude-code"
9
+
10
+
11
+ def _writeback_tool_args(call: Any, tool_args: dict, mode: str | None) -> None:
12
+ """Persist pre-tool callback argument mutations onto ``call.args``.
13
+
14
+ Failures are swallowed because writeback must never block tool execution.
15
+ """
16
+ if mode is None:
17
+ return
18
+ try:
19
+ if mode == "str":
20
+ import json
21
+
22
+ call.args = json.dumps(tool_args)
23
+ elif mode == "dict":
24
+ call.args = tool_args
25
+ except Exception:
26
+ pass
27
+
28
+
29
+ def _tool_args_for_pre_tool_call(call_args: Any) -> tuple[dict, str | None]:
30
+ """Build a best-effort repaired dict view for pre-tool callbacks."""
31
+ if isinstance(call_args, dict):
32
+ return call_args, "dict"
33
+ if not isinstance(call_args, str):
34
+ return {}, None
35
+
36
+ try:
37
+ import json
38
+ import json_repair
39
+
40
+ parsed = json.loads(json_repair.repair_json(call_args))
41
+ if isinstance(parsed, dict):
42
+ return parsed, "str"
43
+ except Exception:
44
+ pass
45
+
46
+ return {"raw": call_args}, None
47
+
48
+
49
+ def _normalize_claude_code_tool_name(tool_manager: Any, name: Any) -> Any:
50
+ """Resolve a wire-prefixed name against this run's actual tool registry."""
51
+ if not isinstance(name, str) or not name.startswith(_CLAUDE_CODE_TOOL_PREFIX):
52
+ return name
53
+
54
+ unprefixed = name[len(_CLAUDE_CODE_TOOL_PREFIX) :]
55
+ tools = getattr(tool_manager, "tools", None)
56
+ if isinstance(tools, dict):
57
+ # A real ``cp_*`` tool wins. Otherwise, normalize when the unprefixed
58
+ # name exists in this run — including private agents whose model may
59
+ # differ from the globally selected interactive model.
60
+ if name in tools:
61
+ return name
62
+ if unprefixed in tools:
63
+ return unprefixed
64
+
65
+ # Compatibility fallback for the brief window before a ToolManager has a
66
+ # prepared registry. Keep this scoped so unrelated providers can own
67
+ # legitimate ``cp_*`` names.
68
+ try:
69
+ from code_puppy.config import get_global_model_name
70
+
71
+ model_name = get_global_model_name() or ""
72
+ if model_name.startswith(_CLAUDE_CODE_MODEL_PREFIX):
73
+ return unprefixed
74
+ except Exception:
75
+ pass
76
+ return name
77
+
78
+
79
+ _GENERIC_BLOCK_REASON = "Tool execution blocked by hook"
80
+
81
+
82
+ def _block_reason(callback_result: dict) -> str:
83
+ """Render a hook's deny reason without ever turning a deny into an allow."""
84
+ try:
85
+ raw = (
86
+ callback_result.get("error_message") or callback_result.get("reason") or ""
87
+ )
88
+ if not isinstance(raw, str):
89
+ raw = str(raw)
90
+ marker = raw.find("[BLOCKED]")
91
+ if marker != -1:
92
+ return raw[marker:].strip() or _GENERIC_BLOCK_REASON
93
+ return raw.strip() or _GENERIC_BLOCK_REASON
94
+ except Exception:
95
+ return _GENERIC_BLOCK_REASON
96
+
97
+
98
+ __all__ = [
99
+ "_block_reason",
100
+ "_normalize_claude_code_tool_name",
101
+ "_tool_args_for_pre_tool_call",
102
+ "_writeback_tool_args",
103
+ ]
@@ -0,0 +1,114 @@
1
+ """Private, one-shot model inference without the conversational agent runtime."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import asyncio
6
+ from collections.abc import Mapping
7
+ from typing import TypeVar
8
+
9
+ from pydantic_ai import Agent, UsageLimits
10
+
11
+ from code_puppy.model_factory import (
12
+ ModelFactory,
13
+ _is_anthropic_model,
14
+ make_model_settings,
15
+ )
16
+
17
+ OutputT = TypeVar("OutputT")
18
+
19
+
20
+ def _disable_chat_template_thinking(model_settings: dict[str, object]) -> None:
21
+ """Disable an already-configured vLLM/SGLang thinking switch in place.
22
+
23
+ ``chat_template_kwargs`` is not part of the OpenAI API. Only preserve and
24
+ override it when model configuration already opted into that extension;
25
+ injecting it for providers such as ChatGPT OAuth causes a 400 response.
26
+ """
27
+ configured_extra_body = model_settings.get("extra_body")
28
+ if not isinstance(configured_extra_body, dict):
29
+ return
30
+
31
+ configured_chat_template = configured_extra_body.get("chat_template_kwargs")
32
+ if not isinstance(configured_chat_template, dict):
33
+ return
34
+
35
+ extra_body = dict(configured_extra_body)
36
+ chat_template_kwargs = dict(configured_chat_template)
37
+ chat_template_kwargs["enable_thinking"] = False
38
+ extra_body["chat_template_kwargs"] = chat_template_kwargs
39
+ model_settings["extra_body"] = extra_body
40
+
41
+
42
+ def _disable_anthropic_thinking(
43
+ model_name: str,
44
+ model_config: dict[str, object],
45
+ model_settings: dict[str, object],
46
+ ) -> None:
47
+ """Explicitly override thinking embedded in Anthropic model defaults."""
48
+ if not _is_anthropic_model(model_name, model_config):
49
+ return
50
+
51
+ model_settings["anthropic_thinking"] = {"type": "disabled"}
52
+
53
+ # Plugin-created Anthropic models carry their own default settings. Agent
54
+ # settings are merged shallowly over those defaults, so explicitly replace
55
+ # extra_body as well or a model-level output_config.effort survives after
56
+ # thinking is disabled.
57
+ extra_body = dict(model_settings.get("extra_body") or {})
58
+ output_config = dict(extra_body.get("output_config") or {})
59
+ output_config.pop("effort", None)
60
+ if output_config:
61
+ extra_body["output_config"] = output_config
62
+ else:
63
+ extra_body.pop("output_config", None)
64
+ model_settings["extra_body"] = extra_body
65
+
66
+
67
+ async def run_private_prompt(
68
+ *,
69
+ model_name: str,
70
+ instructions: str,
71
+ prompt: str,
72
+ output_type: type[OutputT],
73
+ model_settings_overrides: Mapping[str, object] | None = None,
74
+ max_tokens: int = 256,
75
+ timeout_seconds: float = 30,
76
+ ) -> OutputT:
77
+ """Run one structured request without agent hooks, history, tools, or output.
78
+
79
+ Callers own policy for failures: safety checks may fail closed while
80
+ convenience classifiers may fail open.
81
+ """
82
+ models_config = ModelFactory.load_config()
83
+ if model_name not in models_config:
84
+ raise ValueError(f"Unknown private-inference model: {model_name}")
85
+
86
+ model = ModelFactory.get_model(model_name, models_config)
87
+ model_settings = make_model_settings(
88
+ model_name,
89
+ max_tokens=max_tokens,
90
+ overrides=dict(model_settings_overrides or {}),
91
+ )
92
+ _disable_chat_template_thinking(model_settings)
93
+ _disable_anthropic_thinking(
94
+ model_name,
95
+ models_config[model_name],
96
+ model_settings,
97
+ )
98
+ agent = Agent(
99
+ model=model,
100
+ instructions=instructions,
101
+ output_type=output_type,
102
+ retries=0,
103
+ toolsets=[],
104
+ model_settings=model_settings,
105
+ )
106
+ async with asyncio.timeout(timeout_seconds):
107
+ result = await agent.run(
108
+ prompt,
109
+ usage_limits=UsageLimits(request_limit=1),
110
+ )
111
+ return result.output
112
+
113
+
114
+ __all__ = ["run_private_prompt"]
@@ -25,6 +25,13 @@ import logging
25
25
  import warnings
26
26
  from typing import Any
27
27
 
28
+ from code_puppy._pydantic_tool_helpers import (
29
+ _block_reason,
30
+ _normalize_claude_code_tool_name,
31
+ _tool_args_for_pre_tool_call,
32
+ _writeback_tool_args,
33
+ )
34
+
28
35
  logger = logging.getLogger(__name__)
29
36
 
30
37
  # Loud failures recorded during the current apply_all_patches() run, so the
@@ -184,91 +191,6 @@ def patch_tool_call_json_repair() -> bool:
184
191
  )
185
192
 
186
193
 
187
- def _writeback_tool_args(call: Any, tool_args: dict, mode: str | None) -> None:
188
- """Persist pre_tool_call mutations of ``tool_args`` back onto ``call.args``.
189
-
190
- pydantic-ai's ``ToolCallPart.args`` is usually a JSON *string* (what the
191
- LLM emitted). The pre_tool_call hook contract gives plugins a *dict* view
192
- to mutate. Without this writeback, mutations vanish before the real tool
193
- runs and the model sees nothing changed.
194
-
195
- Args:
196
- call: The ``ToolCallPart`` (or compatible) whose ``args`` we update.
197
- tool_args: The dict view that hooks may have mutated.
198
- mode: ``"str"`` to re-serialize as JSON, ``"dict"`` to assign directly,
199
- or ``None`` to skip (unparseable input — don't corrupt it).
200
-
201
- Failures are swallowed: writeback must never block tool execution.
202
- """
203
- if mode is None:
204
- return
205
- try:
206
- if mode == "str":
207
- import json
208
-
209
- call.args = json.dumps(tool_args)
210
- elif mode == "dict":
211
- call.args = tool_args
212
- except Exception:
213
- pass # never block tool execution on writeback failure
214
-
215
-
216
- def _tool_args_for_pre_tool_call(call_args: Any) -> tuple[dict, str | None]:
217
- """Build a best-effort repaired dict view for ``pre_tool_call`` hooks.
218
-
219
- Editors now use model-native names (notably ``edit`` and ``apply_patch``),
220
- so JSON repair belongs at this shared seam instead of in a
221
- ``replace_in_file``-specific path.
222
- """
223
- if isinstance(call_args, dict):
224
- return call_args, "dict"
225
- if not isinstance(call_args, str):
226
- return {}, None
227
-
228
- try:
229
- import json
230
- import json_repair
231
-
232
- parsed = json.loads(json_repair.repair_json(call_args))
233
- if isinstance(parsed, dict):
234
- return parsed, "str"
235
- except Exception:
236
- pass
237
-
238
- # Keep the diagnostic view, but do not write it back and corrupt history.
239
- return {"raw": call_args}, None
240
-
241
-
242
- #: Shown when a hook denies without a usable reason, or when producing its
243
- #: reason fails. A deny always renders as a deny — never as an allow.
244
- _GENERIC_BLOCK_REASON = "Tool execution blocked by hook"
245
-
246
-
247
- def _block_reason(callback_result: dict) -> str:
248
- """Render a hook's deny reason, tolerating any value it supplied.
249
-
250
- `error_message`/`reason` come from plugin code and are not guaranteed to be
251
- strings. A non-string previously raised inside the caller's broad `except`,
252
- which silently turned an explicit deny into an allow.
253
-
254
- Total by construction: extraction is inside the guard too, because `.get`
255
- and the truthiness of a plugin's own object can raise just as easily as
256
- `__str__`, and none of that may escape into the caller.
257
- """
258
- try:
259
- raw = (
260
- callback_result.get("error_message") or callback_result.get("reason") or ""
261
- )
262
- if not isinstance(raw, str):
263
- raw = str(raw)
264
- marker = raw.find("[BLOCKED]")
265
- if marker != -1:
266
- return raw[marker:].strip() or _GENERIC_BLOCK_REASON
267
- return raw.strip() or _GENERIC_BLOCK_REASON
268
- except Exception:
269
- return _GENERIC_BLOCK_REASON
270
-
271
-
272
194
  def patch_tool_call_callbacks() -> bool:
273
195
  """Patch pydantic-ai tool handling to support callbacks and Claude Code tool names.
274
196
 
@@ -277,12 +199,13 @@ def patch_tool_call_callbacks() -> bool:
277
199
  ``_call_tool`` is too late: prefixed tools get marked as ``unknown`` and can
278
200
  burn through result retries, eventually raising ``UnexpectedModelBehavior``.
279
201
 
280
- This patch normalizes Claude Code tool names early (during lookup and
281
- validation, before classification) and wraps ``execute_tool_call`` (the
282
- single execution entry point since pydantic-ai split validation from
283
- execution in the public ``pydantic_ai.tool_manager`` module) so every tool
284
- invocation also triggers the ``pre_tool_call`` and ``post_tool_call``
285
- callbacks defined in ``code_puppy.callbacks``.
202
+ This patch normalizes Claude Code tool names early (during regular and
203
+ structured-output validation, before classification) and wraps
204
+ ``execute_tool_call`` (the single execution entry point since pydantic-ai
205
+ split validation from execution in the public
206
+ ``pydantic_ai.tool_manager`` module) so every tool invocation also triggers
207
+ the ``pre_tool_call`` and ``post_tool_call`` callbacks defined in
208
+ ``code_puppy.callbacks``.
286
209
 
287
210
  Why not the v2 ``Hooks`` capability? Evaluated against pydantic-ai
288
211
  2.31.0 and rejected:
@@ -305,43 +228,13 @@ def patch_tool_call_callbacks() -> bool:
305
228
 
306
229
  _original_execute_tool_call = ToolManager.execute_tool_call
307
230
  _original_get_tool_def = ToolManager.get_tool_def
231
+ _original_validate_output_tool_call = ToolManager.validate_output_tool_call
308
232
  _original_validate_tool_call = ToolManager.validate_tool_call
309
233
 
310
- # Strip the cp_ prefix on return only while a claude-code model is active;
311
- # unconditional stripping would corrupt legit ``cp_`` names from other types.
312
- TOOL_PREFIX = "cp_"
313
- # Matches claude_code_oauth's model-name convention (prompt_handler.py).
314
- _CLAUDE_CODE_MODEL_PREFIX = "claude-code"
315
-
316
- def _is_claude_code_model_active() -> bool:
317
- """Best-effort check: is the currently selected model a claude-code one?
318
-
319
- Lazy-imported so this patch stays safe to apply before config is
320
- initialised; any failure means "not claude-code" so we never
321
- accidentally strip prefixes from non-claude-code tool names.
322
- """
323
- try:
324
- from code_puppy.config import get_global_model_name
325
-
326
- model_name = get_global_model_name() or ""
327
- return model_name.startswith(_CLAUDE_CODE_MODEL_PREFIX)
328
- except Exception:
329
- return False
330
-
331
- def _normalize_tool_name(name: Any) -> Any:
332
- """Strip the ``cp_`` prefix if present (claude-code models only)."""
333
- if (
334
- isinstance(name, str)
335
- and name.startswith(TOOL_PREFIX)
336
- and _is_claude_code_model_active()
337
- ):
338
- return name[len(TOOL_PREFIX) :]
339
- return name
340
-
341
- def _normalize_call_tool_name(call: Any) -> tuple[Any, Any]:
234
+ def _normalize_call_tool_name(self: Any, call: Any) -> tuple[Any, Any]:
342
235
  """Normalize the tool_name on a call object in-place."""
343
236
  tool_name = getattr(call, "tool_name", None)
344
- normalized_name = _normalize_tool_name(tool_name)
237
+ normalized_name = _normalize_claude_code_tool_name(self, tool_name)
345
238
  if normalized_name != tool_name:
346
239
  try:
347
240
  call.tool_name = normalized_name
@@ -353,18 +246,24 @@ def patch_tool_call_callbacks() -> bool:
353
246
  # Run before classification so prefixed names resolve correctly.
354
247
 
355
248
  def _patched_get_tool_def(self, name: str):
356
- return _original_get_tool_def(self, _normalize_tool_name(name))
249
+ normalized_name = _normalize_claude_code_tool_name(self, name)
250
+ return _original_get_tool_def(self, normalized_name)
357
251
 
358
252
  async def _patched_validate_tool_call(self, call, **kwargs):
359
253
  """Normalize the tool name before pydantic-ai classifies the call."""
360
- _normalize_call_tool_name(call)
254
+ _normalize_call_tool_name(self, call)
361
255
  return await _original_validate_tool_call(self, call, **kwargs)
362
256
 
257
+ async def _patched_validate_output_tool_call(self, call, **kwargs):
258
+ """Normalize names used by structured result output tools."""
259
+ _normalize_call_tool_name(self, call)
260
+ return await _original_validate_output_tool_call(self, call, **kwargs)
261
+
363
262
  # -- execute_tool_call wrapper with callbacks ----------------------------
364
263
 
365
264
  async def _patched_execute_tool_call(self, validated, **kwargs):
366
265
  call = validated.call
367
- tool_name, call = _normalize_call_tool_name(call)
266
+ tool_name, call = _normalize_call_tool_name(self, call)
368
267
 
369
268
  # Give hooks a dict view of the args. Prefer the already-validated
370
269
  # dict — execution passes it to the tool, so in-place mutations
@@ -469,9 +368,13 @@ def patch_tool_call_callbacks() -> bool:
469
368
  pass # never block tool execution
470
369
 
471
370
  ToolManager.get_tool_def = _patched_get_tool_def
371
+ ToolManager.validate_output_tool_call = _patched_validate_output_tool_call
472
372
  ToolManager.validate_tool_call = _patched_validate_tool_call
473
373
  ToolManager.execute_tool_call = _patched_execute_tool_call
474
374
  assert ToolManager.get_tool_def is _patched_get_tool_def
375
+ assert (
376
+ ToolManager.validate_output_tool_call is _patched_validate_output_tool_call
377
+ )
475
378
  assert ToolManager.validate_tool_call is _patched_validate_tool_call
476
379
  assert ToolManager.execute_tool_call is _patched_execute_tool_call
477
380
  return True
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "code-puppy"
7
- version = "0.0.802"
7
+ version = "0.0.804"
8
8
  description = "Code generation agent"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11,<3.15"
File without changes
File without changes
File without changes