code-puppy 0.0.561__tar.gz → 0.0.563__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 (373) hide show
  1. {code_puppy-0.0.561 → code_puppy-0.0.563}/PKG-INFO +1 -1
  2. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/agents/event_stream_handler.py +92 -21
  3. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/agents/run_stats.py +276 -4
  4. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/set_menu_catalog.py +14 -0
  5. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/config.py +45 -0
  6. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/messaging/renderers.py +101 -0
  7. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/messaging/rich_renderer.py +170 -13
  8. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/messaging/spinner/__init__.py +14 -2
  9. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/puppy_kennel/README.md +19 -12
  10. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/puppy_kennel/config.py +3 -4
  11. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/puppy_kennel/register_callbacks.py +1 -2
  12. code_puppy-0.0.563/code_puppy/plugins/puppy_kennel/state.py +54 -0
  13. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/tools/display.py +5 -3
  14. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/tools/file_operations.py +3 -0
  15. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/tools/subagent_invocation.py +50 -10
  16. {code_puppy-0.0.561 → code_puppy-0.0.563}/pyproject.toml +1 -1
  17. code_puppy-0.0.561/code_puppy/plugins/puppy_kennel/state.py +0 -42
  18. {code_puppy-0.0.561 → code_puppy-0.0.563}/.gitignore +0 -0
  19. {code_puppy-0.0.561 → code_puppy-0.0.563}/LICENSE +0 -0
  20. {code_puppy-0.0.561 → code_puppy-0.0.563}/README.md +0 -0
  21. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/__init__.py +0 -0
  22. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/__main__.py +0 -0
  23. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/agents/__init__.py +0 -0
  24. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/agents/_builder.py +0 -0
  25. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/agents/_compaction.py +0 -0
  26. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/agents/_diagnostics.py +0 -0
  27. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/agents/_history.py +0 -0
  28. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/agents/_key_listeners.py +0 -0
  29. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/agents/_non_streaming_render.py +0 -0
  30. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/agents/_run_signals.py +0 -0
  31. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/agents/_runtime.py +0 -0
  32. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/agents/_steer_processor.py +0 -0
  33. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/agents/agent_code_puppy.py +0 -0
  34. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/agents/agent_creator_agent.py +0 -0
  35. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/agents/agent_helios.py +0 -0
  36. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/agents/agent_manager.py +0 -0
  37. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/agents/agent_planning.py +0 -0
  38. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/agents/agent_qa_kitten.py +0 -0
  39. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/agents/base_agent.py +0 -0
  40. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/agents/json_agent.py +0 -0
  41. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/agents/smooth_stream.py +0 -0
  42. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/agents/subagent_stream_handler.py +0 -0
  43. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/callbacks.py +0 -0
  44. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/chatgpt_codex_client.py +0 -0
  45. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/claude_cache_client.py +0 -0
  46. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/cli_runner.py +0 -0
  47. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/__init__.py +0 -0
  48. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/add_model_menu.py +0 -0
  49. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/agent_menu.py +0 -0
  50. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/attachments.py +0 -0
  51. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/autosave_menu.py +0 -0
  52. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/clipboard.py +0 -0
  53. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/colors_menu.py +0 -0
  54. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/command_handler.py +0 -0
  55. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/command_registry.py +0 -0
  56. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/config_apply.py +0 -0
  57. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/config_commands.py +0 -0
  58. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/core_commands.py +0 -0
  59. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/diff_menu.py +0 -0
  60. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/file_index.py +0 -0
  61. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/file_path_completion.py +0 -0
  62. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/judges_menu.py +0 -0
  63. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/load_context_completion.py +0 -0
  64. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/mcp/__init__.py +0 -0
  65. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/mcp/base.py +0 -0
  66. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/mcp/catalog_server_installer.py +0 -0
  67. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/mcp/custom_server_form.py +0 -0
  68. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/mcp/custom_server_installer.py +0 -0
  69. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/mcp/edit_command.py +0 -0
  70. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/mcp/handler.py +0 -0
  71. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/mcp/help_command.py +0 -0
  72. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/mcp/install_command.py +0 -0
  73. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/mcp/install_menu.py +0 -0
  74. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/mcp/list_command.py +0 -0
  75. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/mcp/logs_command.py +0 -0
  76. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/mcp/remove_command.py +0 -0
  77. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/mcp/restart_command.py +0 -0
  78. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/mcp/search_command.py +0 -0
  79. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/mcp/silence_warning_command.py +0 -0
  80. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/mcp/start_all_command.py +0 -0
  81. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/mcp/start_command.py +0 -0
  82. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/mcp/status_command.py +0 -0
  83. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/mcp/stop_all_command.py +0 -0
  84. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/mcp/stop_command.py +0 -0
  85. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/mcp/utils.py +0 -0
  86. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/mcp/wizard_utils.py +0 -0
  87. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/mcp_binding_menu.py +0 -0
  88. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/mcp_completion.py +0 -0
  89. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/model_picker_completion.py +0 -0
  90. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/model_settings_menu.py +0 -0
  91. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/onboarding_slides.py +0 -0
  92. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/onboarding_wizard.py +0 -0
  93. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/pagination.py +0 -0
  94. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/pin_command_completion.py +0 -0
  95. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/prompt_toolkit_completion.py +0 -0
  96. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/session_commands.py +0 -0
  97. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/set_menu.py +0 -0
  98. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/set_menu_render.py +0 -0
  99. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/set_menu_schema.py +0 -0
  100. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/set_menu_settings.py +0 -0
  101. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/set_menu_shims.py +0 -0
  102. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/set_menu_values.py +0 -0
  103. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/shell_passthrough.py +0 -0
  104. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/skills_completion.py +0 -0
  105. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/uc_menu.py +0 -0
  106. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/utils.py +0 -0
  107. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/command_line/wiggum_state.py +0 -0
  108. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/error_logging.py +0 -0
  109. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/gemini_code_assist.py +0 -0
  110. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/gemini_model.py +0 -0
  111. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/hook_engine/README.md +0 -0
  112. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/hook_engine/__init__.py +0 -0
  113. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/hook_engine/aliases.py +0 -0
  114. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/hook_engine/engine.py +0 -0
  115. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/hook_engine/executor.py +0 -0
  116. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/hook_engine/matcher.py +0 -0
  117. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/hook_engine/models.py +0 -0
  118. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/hook_engine/registry.py +0 -0
  119. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/hook_engine/validator.py +0 -0
  120. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/http_utils.py +0 -0
  121. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/keymap.py +0 -0
  122. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/list_filtering.py +0 -0
  123. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/main.py +0 -0
  124. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/mcp_/__init__.py +0 -0
  125. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/mcp_/agent_bindings.py +0 -0
  126. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/mcp_/async_lifecycle.py +0 -0
  127. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/mcp_/blocking_startup.py +0 -0
  128. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/mcp_/captured_stdio_server.py +0 -0
  129. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/mcp_/circuit_breaker.py +0 -0
  130. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/mcp_/config_wizard.py +0 -0
  131. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/mcp_/dashboard.py +0 -0
  132. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/mcp_/error_isolation.py +0 -0
  133. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/mcp_/examples/retry_example.py +0 -0
  134. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/mcp_/health_monitor.py +0 -0
  135. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/mcp_/managed_server.py +0 -0
  136. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/mcp_/manager.py +0 -0
  137. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/mcp_/mcp_logs.py +0 -0
  138. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/mcp_/registry.py +0 -0
  139. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/mcp_/retry_manager.py +0 -0
  140. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/mcp_/server_registry_catalog.py +0 -0
  141. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/mcp_/status_tracker.py +0 -0
  142. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/mcp_/system_tools.py +0 -0
  143. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/mcp_prompts/__init__.py +0 -0
  144. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/mcp_prompts/hook_creator.py +0 -0
  145. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/messaging/__init__.py +0 -0
  146. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/messaging/bus.py +0 -0
  147. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/messaging/commands.py +0 -0
  148. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/messaging/markdown_patches.py +0 -0
  149. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/messaging/message_queue.py +0 -0
  150. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/messaging/messages.py +0 -0
  151. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/messaging/pause_controller.py +0 -0
  152. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/messaging/queue_console.py +0 -0
  153. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/messaging/spinner/console_spinner.py +0 -0
  154. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/messaging/spinner/spinner_base.py +0 -0
  155. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/messaging/subagent_console.py +0 -0
  156. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/model_descriptions.py +0 -0
  157. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/model_factory.py +0 -0
  158. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/model_switching.py +0 -0
  159. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/model_utils.py +0 -0
  160. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/models.json +0 -0
  161. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/models_dev_api.json +0 -0
  162. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/models_dev_parser.py +0 -0
  163. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/__init__.py +0 -0
  164. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/agent_skills/__init__.py +0 -0
  165. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/agent_skills/config.py +0 -0
  166. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/agent_skills/discovery.py +0 -0
  167. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/agent_skills/downloader.py +0 -0
  168. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/agent_skills/enabled_skills.py +0 -0
  169. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/agent_skills/installer.py +0 -0
  170. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/agent_skills/metadata.py +0 -0
  171. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/agent_skills/prompt_builder.py +0 -0
  172. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/agent_skills/register_callbacks.py +0 -0
  173. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/agent_skills/remote_catalog.py +0 -0
  174. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/agent_skills/skill_catalog.py +0 -0
  175. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/agent_skills/skill_commands.py +0 -0
  176. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/agent_skills/skills_install_menu.py +0 -0
  177. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/agent_skills/skills_menu.py +0 -0
  178. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/agent_steering/README.md +0 -0
  179. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/agent_steering/__init__.py +0 -0
  180. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/agent_steering/line_editor.py +0 -0
  181. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/agent_steering/register_callbacks.py +0 -0
  182. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/agent_steering/steering_prompt.py +0 -0
  183. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/aws_bedrock/__init__.py +0 -0
  184. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/aws_bedrock/config.py +0 -0
  185. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/aws_bedrock/register_callbacks.py +0 -0
  186. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/aws_bedrock/utils.py +0 -0
  187. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/azure_foundry/README.md +0 -0
  188. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/azure_foundry/__init__.py +0 -0
  189. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/azure_foundry/config.py +0 -0
  190. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/azure_foundry/discovery.py +0 -0
  191. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/azure_foundry/register_callbacks.py +0 -0
  192. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/azure_foundry/token.py +0 -0
  193. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/azure_foundry/utils.py +0 -0
  194. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/chatgpt_oauth/__init__.py +0 -0
  195. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/chatgpt_oauth/config.py +0 -0
  196. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/chatgpt_oauth/oauth_flow.py +0 -0
  197. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/chatgpt_oauth/register_callbacks.py +0 -0
  198. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/chatgpt_oauth/test_plugin.py +0 -0
  199. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/chatgpt_oauth/utils.py +0 -0
  200. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/claude_code_hooks/__init__.py +0 -0
  201. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/claude_code_hooks/config.py +0 -0
  202. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/claude_code_hooks/register_callbacks.py +0 -0
  203. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/claude_code_oauth/README.md +0 -0
  204. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/claude_code_oauth/SETUP.md +0 -0
  205. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/claude_code_oauth/__init__.py +0 -0
  206. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/claude_code_oauth/config.py +0 -0
  207. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/claude_code_oauth/fast_mode.py +0 -0
  208. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/claude_code_oauth/prompt_handler.py +0 -0
  209. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/claude_code_oauth/register_callbacks.py +0 -0
  210. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/claude_code_oauth/test_fast_mode.py +0 -0
  211. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/claude_code_oauth/test_plugin.py +0 -0
  212. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/claude_code_oauth/token_refresh_heartbeat.py +0 -0
  213. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/claude_code_oauth/utils.py +0 -0
  214. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/config.py +0 -0
  215. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/context_indicator/__init__.py +0 -0
  216. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/context_indicator/register_callbacks.py +0 -0
  217. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/context_indicator/usage.py +0 -0
  218. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/copilot_auth/__init__.py +0 -0
  219. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/copilot_auth/config.py +0 -0
  220. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/copilot_auth/reasoning_client.py +0 -0
  221. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/copilot_auth/register_callbacks.py +0 -0
  222. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/copilot_auth/utils.py +0 -0
  223. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/customizable_commands/__init__.py +0 -0
  224. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/customizable_commands/register_callbacks.py +0 -0
  225. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/dbos_durable_exec/__init__.py +0 -0
  226. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/dbos_durable_exec/cancel.py +0 -0
  227. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/dbos_durable_exec/commands.py +0 -0
  228. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/dbos_durable_exec/config.py +0 -0
  229. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/dbos_durable_exec/lifecycle.py +0 -0
  230. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/dbos_durable_exec/register_callbacks.py +0 -0
  231. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/dbos_durable_exec/runtime.py +0 -0
  232. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/dbos_durable_exec/workflow_ids.py +0 -0
  233. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/dbos_durable_exec/wrapper.py +0 -0
  234. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/destructive_command_guard/__init__.py +0 -0
  235. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/destructive_command_guard/detector.py +0 -0
  236. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/destructive_command_guard/register_callbacks.py +0 -0
  237. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/emoji_filter/__init__.py +0 -0
  238. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/emoji_filter/config.py +0 -0
  239. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/emoji_filter/register_callbacks.py +0 -0
  240. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/emoji_filter/stripper.py +0 -0
  241. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/example_custom_command/README.md +0 -0
  242. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/example_custom_command/register_callbacks.py +0 -0
  243. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/file_permission_handler/__init__.py +0 -0
  244. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/file_permission_handler/register_callbacks.py +0 -0
  245. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/force_push_guard/__init__.py +0 -0
  246. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/force_push_guard/detector.py +0 -0
  247. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/force_push_guard/register_callbacks.py +0 -0
  248. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/force_push_guard/test_detector.py +0 -0
  249. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/frontend_emitter/__init__.py +0 -0
  250. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/frontend_emitter/emitter.py +0 -0
  251. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/frontend_emitter/register_callbacks.py +0 -0
  252. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/frontend_emitter/session_context.py +0 -0
  253. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/hook_creator/__init__.py +0 -0
  254. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/hook_creator/register_callbacks.py +0 -0
  255. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/hook_manager/__init__.py +0 -0
  256. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/hook_manager/config.py +0 -0
  257. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/hook_manager/hooks_menu.py +0 -0
  258. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/hook_manager/register_callbacks.py +0 -0
  259. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/oauth_puppy_html.py +0 -0
  260. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/obsidian_agent/README.md +0 -0
  261. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/obsidian_agent/__init__.py +0 -0
  262. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/obsidian_agent/agent_obsidian.py +0 -0
  263. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/obsidian_agent/register_callbacks.py +0 -0
  264. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/ollama/__init__.py +0 -0
  265. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/ollama/register_callbacks.py +0 -0
  266. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/ollama_setup/__init__.py +0 -0
  267. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/ollama_setup/completer.py +0 -0
  268. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/ollama_setup/register_callbacks.py +0 -0
  269. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/plugin_list/__init__.py +0 -0
  270. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/plugin_list/plugins_menu.py +0 -0
  271. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/plugin_list/register_callbacks.py +0 -0
  272. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/pop_command/__init__.py +0 -0
  273. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/pop_command/register_callbacks.py +0 -0
  274. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/prompt_newline/__init__.py +0 -0
  275. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/prompt_newline/config.py +0 -0
  276. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/prompt_newline/register_callbacks.py +0 -0
  277. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/prune/__init__.py +0 -0
  278. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/prune/prune_menu.py +0 -0
  279. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/prune/prune_model.py +0 -0
  280. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/prune/prune_render.py +0 -0
  281. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/prune/register_callbacks.py +0 -0
  282. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/puppy_kennel/__init__.py +0 -0
  283. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/puppy_kennel/commands.py +0 -0
  284. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/puppy_kennel/kennel.py +0 -0
  285. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/puppy_kennel/packer.py +0 -0
  286. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/puppy_kennel/recorder.py +0 -0
  287. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/puppy_kennel/retriever.py +0 -0
  288. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/puppy_kennel/schema.py +0 -0
  289. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/puppy_kennel/tools.py +0 -0
  290. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/puppy_kennel/wings.py +0 -0
  291. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/review_pr/__init__.py +0 -0
  292. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/review_pr/register_callbacks.py +0 -0
  293. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/shell_safety/__init__.py +0 -0
  294. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/shell_safety/agent_shell_safety.py +0 -0
  295. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/shell_safety/command_cache.py +0 -0
  296. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/shell_safety/register_callbacks.py +0 -0
  297. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/statusline/__init__.py +0 -0
  298. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/statusline/config.py +0 -0
  299. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/statusline/payload.py +0 -0
  300. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/statusline/prompt_patch.py +0 -0
  301. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/statusline/register_callbacks.py +0 -0
  302. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/statusline/runner.py +0 -0
  303. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/statusline/statusline_command.py +0 -0
  304. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/switch_agent_resume/__init__.py +0 -0
  305. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/switch_agent_resume/register_callbacks.py +0 -0
  306. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/synthetic_status/__init__.py +0 -0
  307. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/synthetic_status/register_callbacks.py +0 -0
  308. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/synthetic_status/status_api.py +0 -0
  309. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/theme/README.md +0 -0
  310. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/theme/__init__.py +0 -0
  311. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/theme/bundled_palettes.py +0 -0
  312. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/theme/content_styles.py +0 -0
  313. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/theme/osc_palette.py +0 -0
  314. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/theme/picker.py +0 -0
  315. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/theme/register_callbacks.py +0 -0
  316. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/theme/rich_themes.py +0 -0
  317. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/theme/themes.py +0 -0
  318. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/token_ratio_learner/__init__.py +0 -0
  319. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/token_ratio_learner/ratios.py +0 -0
  320. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/token_ratio_learner/register_callbacks.py +0 -0
  321. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/universal_constructor/__init__.py +0 -0
  322. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/universal_constructor/models.py +0 -0
  323. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/universal_constructor/register_callbacks.py +0 -0
  324. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/universal_constructor/registry.py +0 -0
  325. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/universal_constructor/sandbox.py +0 -0
  326. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/wide_completion_menu/__init__.py +0 -0
  327. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/wide_completion_menu/register_callbacks.py +0 -0
  328. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/wiggum/__init__.py +0 -0
  329. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/wiggum/judge.py +0 -0
  330. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/wiggum/judge_config.py +0 -0
  331. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/wiggum/register_callbacks.py +0 -0
  332. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/plugins/wiggum/state.py +0 -0
  333. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/provider_credentials.py +0 -0
  334. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/provider_identity.py +0 -0
  335. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/pydantic_patches.py +0 -0
  336. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/reopenable_async_client.py +0 -0
  337. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/round_robin_model.py +0 -0
  338. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/session_storage.py +0 -0
  339. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/status_display.py +0 -0
  340. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/summarization_agent.py +0 -0
  341. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/terminal_utils.py +0 -0
  342. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/tools/__init__.py +0 -0
  343. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/tools/agent_tools.py +0 -0
  344. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/tools/ask_user_question/__init__.py +0 -0
  345. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/tools/ask_user_question/constants.py +0 -0
  346. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/tools/ask_user_question/demo_tui.py +0 -0
  347. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/tools/ask_user_question/handler.py +0 -0
  348. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/tools/ask_user_question/models.py +0 -0
  349. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/tools/ask_user_question/registration.py +0 -0
  350. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/tools/ask_user_question/renderers.py +0 -0
  351. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/tools/ask_user_question/terminal_ui.py +0 -0
  352. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/tools/ask_user_question/theme.py +0 -0
  353. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/tools/ask_user_question/tui_loop.py +0 -0
  354. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/tools/browser/__init__.py +0 -0
  355. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/tools/browser/browser_control.py +0 -0
  356. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/tools/browser/browser_interactions.py +0 -0
  357. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/tools/browser/browser_locators.py +0 -0
  358. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/tools/browser/browser_manager.py +0 -0
  359. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/tools/browser/browser_navigation.py +0 -0
  360. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/tools/browser/browser_screenshot.py +0 -0
  361. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/tools/browser/browser_scripts.py +0 -0
  362. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/tools/browser/browser_workflows.py +0 -0
  363. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/tools/command_runner.py +0 -0
  364. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/tools/common.py +0 -0
  365. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/tools/file_modifications.py +0 -0
  366. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/tools/image_tools.py +0 -0
  367. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/tools/model_tools.py +0 -0
  368. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/tools/skills_tools.py +0 -0
  369. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/tools/subagent_context.py +0 -0
  370. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/tools/tools_content.py +0 -0
  371. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/tools/universal_constructor.py +0 -0
  372. {code_puppy-0.0.561 → code_puppy-0.0.563}/code_puppy/uvx_detection.py +0 -0
  373. {code_puppy-0.0.561 → code_puppy-0.0.563}/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.561
3
+ Version: 0.0.563
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
@@ -25,7 +25,12 @@ from code_puppy.agents.smooth_stream import (
25
25
  make_smooth_termflow_writer,
26
26
  make_thinking_smoother,
27
27
  )
28
- from code_puppy.config import get_banner_color, get_subagent_verbose
28
+ from code_puppy.config import (
29
+ get_banner_color,
30
+ get_output_level,
31
+ get_subagent_verbose,
32
+ get_suppress_thinking_messages,
33
+ )
29
34
  from code_puppy.messaging.spinner import pause_all_spinners, resume_all_spinners
30
35
  from code_puppy.tools.subagent_context import is_subagent
31
36
 
@@ -86,12 +91,41 @@ def get_streaming_console() -> Console:
86
91
  def _should_suppress_output() -> bool:
87
92
  """Check if sub-agent output should be suppressed.
88
93
 
94
+ In ``high`` output mode, sub-agent output is never suppressed.
95
+
89
96
  Returns:
90
97
  True if we're in a sub-agent context and verbose mode is disabled.
91
98
  """
99
+ if get_output_level() == "high":
100
+ return False
92
101
  return is_subagent() and not get_subagent_verbose()
93
102
 
94
103
 
104
+ def _suppress_thinking_stream() -> bool:
105
+ """Return True if thinking banners/content should be hidden.
106
+
107
+ Thinking is suppressed in ``low`` output mode (collapsed to a peek
108
+ by the RichConsoleRenderer) or when the user has explicitly set
109
+ ``suppress_thinking_messages``.
110
+
111
+ In ``high`` output mode, thinking is *never* suppressed -- the user
112
+ explicitly asked for maximum visibility.
113
+ """
114
+ level = get_output_level()
115
+ if level == "high":
116
+ return False
117
+ return level == "low" or get_suppress_thinking_messages()
118
+
119
+
120
+ def _suppress_tool_progress() -> bool:
121
+ """Return True if tool-call progress counters should be hidden.
122
+
123
+ In ``low`` mode, the shell-start peek in the RichConsoleRenderer is
124
+ sufficient; the streaming token counter is noise.
125
+ """
126
+ return get_output_level() == "low"
127
+
128
+
95
129
  async def event_stream_handler(
96
130
  ctx: RunContext,
97
131
  events: AsyncIterable[Any],
@@ -130,7 +164,9 @@ async def event_stream_handler(
130
164
  banner_printed: set[int] = set() # Track if banner was already printed
131
165
  token_count: dict[int, int] = {} # Track token count per text/tool part
132
166
  tool_names: dict[int, str] = {} # Track tool name per tool part index
167
+ tool_args_buffer: dict[int, str] = {} # Accumulate raw tool-call args JSON
133
168
  did_stream_anything = False # Track if we streamed any content
169
+ is_high_mode = get_output_level() == "high"
134
170
 
135
171
  # Termflow streaming state for text parts
136
172
  termflow_parsers: dict[int, TermflowParser] = {}
@@ -188,6 +224,7 @@ async def event_stream_handler(
188
224
  console.print() # Newline before banner
189
225
  # Bold banner with configurable color and lightning bolt
190
226
  thinking_color = get_banner_color("thinking")
227
+
191
228
  console.print(
192
229
  Text.from_markup(
193
230
  f"[bold white on {thinking_color}] THINKING [/bold white on {thinking_color}] [dim]\u26a1 "
@@ -267,9 +304,11 @@ async def event_stream_handler(
267
304
  streaming_parts.add(event.index)
268
305
  thinking_parts.add(event.index)
269
306
  # If there's initial content, print banner + content now
307
+ # (unless thinking is suppressed by output level or toggle).
270
308
  if part.content and part.content.strip():
271
- await _print_thinking_banner()
272
- _emit_thinking(event.index, part.content)
309
+ if not _suppress_thinking_stream():
310
+ await _print_thinking_banner()
311
+ _emit_thinking(event.index, part.content)
273
312
  banner_printed.add(event.index)
274
313
  elif isinstance(part, TextPart):
275
314
  streaming_parts.add(event.index)
@@ -287,6 +326,7 @@ async def event_stream_handler(
287
326
  streaming_parts.add(event.index)
288
327
  tool_parts.add(event.index)
289
328
  token_count[event.index] = 0 # Initialize token counter
329
+ tool_args_buffer[event.index] = "" # Accumulate JSON args
290
330
  # Capture tool name from the start event
291
331
  tool_names[event.index] = part.tool_name or ""
292
332
  # Track tool name for display
@@ -336,10 +376,12 @@ async def event_stream_handler(
336
376
  else:
337
377
  # For thinking parts, stream smoothly (dim) via a
338
378
  # rate-limited buffer so bursty deltas don't stutter.
339
- if event.index not in banner_printed:
340
- await _print_thinking_banner()
341
- banner_printed.add(event.index)
342
- _emit_thinking(event.index, delta.content_delta)
379
+ # Gate on output level / suppress_thinking toggle.
380
+ if not _suppress_thinking_stream():
381
+ if event.index not in banner_printed:
382
+ await _print_thinking_banner()
383
+ banner_printed.add(event.index)
384
+ _emit_thinking(event.index, delta.content_delta)
343
385
  elif isinstance(delta, ToolCallPartDelta):
344
386
  # For tool calls, estimate tokens from args_delta content
345
387
  # args_delta contains the streaming JSON arguments
@@ -348,6 +390,10 @@ async def event_stream_handler(
348
390
  # Same 2.5 chars/token heuristic as BaseAgent and file_operations
349
391
  estimated_tokens = max(1, math.floor(len(args_delta) / 2.5))
350
392
  token_count[event.index] += estimated_tokens
393
+ # Accumulate raw args JSON for high-mode display.
394
+ tool_args_buffer[event.index] = (
395
+ tool_args_buffer.get(event.index, "") + args_delta
396
+ )
351
397
  else:
352
398
  # Even empty deltas count as activity
353
399
  token_count[event.index] += 1
@@ -359,20 +405,23 @@ async def event_stream_handler(
359
405
  tool_names.get(event.index, "") + tool_name_delta
360
406
  )
361
407
 
362
- # Use stored tool name for display
363
- tool_name = tool_names.get(event.index, "")
364
- count = token_count[event.index]
365
- # Display with tool wrench icon and tool name
366
- if tool_name:
367
- console.print(
368
- f" \U0001f527 Calling {tool_name}... {count} token(s) ",
369
- end="\r",
370
- )
371
- else:
372
- console.print(
373
- f" \U0001f527 Calling tool... {count} token(s) ",
374
- end="\r",
375
- )
408
+ # Use stored tool name for display.
409
+ # In low mode, skip the progress counter — the
410
+ # RichConsoleRenderer peek is sufficient.
411
+ if not _suppress_tool_progress():
412
+ tool_name = tool_names.get(event.index, "")
413
+ count = token_count[event.index]
414
+ # Display with tool wrench icon and tool name
415
+ if tool_name:
416
+ console.print(
417
+ f" \U0001f527 Calling {tool_name}... {count} token(s) ",
418
+ end="\r",
419
+ )
420
+ else:
421
+ console.print(
422
+ f" \U0001f527 Calling tool... {count} token(s) ",
423
+ end="\r",
424
+ )
376
425
 
377
426
  # PartEndEvent - finish the streaming with a newline
378
427
  elif isinstance(event, PartEndEvent):
@@ -417,6 +466,27 @@ async def event_stream_handler(
417
466
  elif event.index in tool_parts:
418
467
  # Clear the chunk counter line by printing spaces and returning
419
468
  console.print(" " * 50, end="\r")
469
+ # In high mode, dump the full tool call arguments so the
470
+ # user can see exactly what the model sent to the tool.
471
+ if is_high_mode:
472
+ tool_name = tool_names.get(event.index, "tool")
473
+ raw_args = tool_args_buffer.get(event.index, "")
474
+ if raw_args:
475
+ # Pretty-print the JSON if possible.
476
+ import json as _json
477
+
478
+ try:
479
+ parsed = _json.loads(raw_args)
480
+ formatted = _json.dumps(
481
+ parsed, indent=2, ensure_ascii=False
482
+ )
483
+ except (ValueError, TypeError):
484
+ formatted = raw_args
485
+ console.print(
486
+ f"[dim] tool_call {escape(tool_name)} args:[/dim]"
487
+ )
488
+ for arg_line in formatted.splitlines():
489
+ console.print(f"[dim] {escape(arg_line)}[/dim]")
420
490
  # For thinking parts, drain the smoother then print newline
421
491
  elif event.index in thinking_parts:
422
492
  smoother = thinking_smoothers.pop(event.index, None)
@@ -429,6 +499,7 @@ async def event_stream_handler(
429
499
  # Clean up token count and tool names
430
500
  token_count.pop(event.index, None)
431
501
  tool_names.pop(event.index, None)
502
+ tool_args_buffer.pop(event.index, None)
432
503
  # Clean up all tracking sets
433
504
  streaming_parts.discard(event.index)
434
505
  thinking_parts.discard(event.index)
@@ -70,12 +70,16 @@ class AgentRunStats:
70
70
  _last_token_time: float = 0.0
71
71
  _gen_seconds: float = 0.0
72
72
  _output_tokens: int = 0
73
+ _current_model_name: str = ""
73
74
 
74
75
  # Snapshot of the most-recently-finished cycle. Used as a fallback so
75
76
  # consumers (telemetry, future displays) have something stable to read
76
77
  # between cycles instead of seeing zeros.
77
78
  _last_ttft_seconds: float = 0.0
78
79
  _last_gen_tps: float = 0.0
80
+ _last_output_tokens: int = 0
81
+ _last_gen_seconds: float = 0.0
82
+ _last_model_name: str = ""
79
83
 
80
84
  # --------------- conversation-wide aggregates ---------------
81
85
  # Summed across every model call in the session so we can report
@@ -87,7 +91,7 @@ class AgentRunStats:
87
91
 
88
92
  # ----------------- API -----------------
89
93
  @classmethod
90
- def mark_request_start(cls) -> None:
94
+ def mark_request_start(cls, model_name: str = "") -> None:
91
95
  """Mark T0 = true request-start (called by ``agent_run_start`` hook).
92
96
 
93
97
  Resets per-cycle counters but preserves conversation-wide aggregates
@@ -99,6 +103,7 @@ class AgentRunStats:
99
103
  cls._last_token_time = 0.0
100
104
  cls._gen_seconds = 0.0
101
105
  cls._output_tokens = 0
106
+ cls._current_model_name = model_name
102
107
 
103
108
  @classmethod
104
109
  def record_output_tokens(cls, tokens: int) -> None:
@@ -127,7 +132,9 @@ class AgentRunStats:
127
132
  cls._output_tokens += int(tokens)
128
133
 
129
134
  @classmethod
130
- def snapshot_cycle_into_aggregates(cls) -> None:
135
+ def snapshot_cycle_into_aggregates(
136
+ cls,
137
+ ) -> None:
131
138
  """Fold the just-finished cycle into conversation-wide aggregates.
132
139
 
133
140
  Called by the ``agent_run_end`` hook so the auto-save line reflects
@@ -136,22 +143,46 @@ class AgentRunStats:
136
143
  starts cleanly.
137
144
  """
138
145
  with cls._lock:
146
+ cls._last_model_name = cls._current_model_name
139
147
  if cls._first_token_time > 0.0 and cls._stream_start_time > 0.0:
140
148
  ttft = cls._first_token_time - cls._stream_start_time
141
149
  if ttft > 0:
142
150
  cls._last_ttft_seconds = ttft
143
151
  cls._total_ttft_seconds += ttft
144
152
  cls._ttft_sample_count += 1
153
+ cls._last_output_tokens = cls._output_tokens
154
+ cls._last_gen_seconds = cls._gen_seconds
145
155
  if cls._output_tokens > 0 and cls._gen_seconds > 0:
146
156
  cls._last_gen_tps = cls._output_tokens / cls._gen_seconds
147
157
  cls._total_output_tokens += cls._output_tokens
148
158
  cls._total_gen_seconds += cls._gen_seconds
159
+ else:
160
+ cls._last_output_tokens = 0
161
+ cls._last_gen_seconds = 0.0
162
+
149
163
  # Zero per-cycle state so the next run starts cleanly.
150
164
  cls._stream_start_time = 0.0
151
165
  cls._first_token_time = 0.0
152
166
  cls._last_token_time = 0.0
153
167
  cls._gen_seconds = 0.0
154
168
  cls._output_tokens = 0
169
+ cls._current_model_name = ""
170
+
171
+ @classmethod
172
+ def get_last_cycle_stats(cls) -> dict:
173
+ """Return a snapshot of the most-recently-completed cycle.
174
+
175
+ Keys: ``model``, ``ttft_seconds``, ``gen_tps``, ``gen_seconds``,
176
+ ``output_tokens``.
177
+ """
178
+ with cls._lock:
179
+ return {
180
+ "model": cls._last_model_name,
181
+ "ttft_seconds": cls._last_ttft_seconds,
182
+ "gen_tps": cls._last_gen_tps,
183
+ "gen_seconds": cls._last_gen_seconds,
184
+ "output_tokens": cls._last_output_tokens,
185
+ }
155
186
 
156
187
  @classmethod
157
188
  def reset_cycle_state(cls) -> None:
@@ -166,8 +197,12 @@ class AgentRunStats:
166
197
  cls._last_token_time = 0.0
167
198
  cls._gen_seconds = 0.0
168
199
  cls._output_tokens = 0
200
+ cls._current_model_name = ""
169
201
  cls._last_ttft_seconds = 0.0
170
202
  cls._last_gen_tps = 0.0
203
+ cls._last_output_tokens = 0
204
+ cls._last_gen_seconds = 0.0
205
+ cls._last_model_name = ""
171
206
 
172
207
  @classmethod
173
208
  def reset_conversation_stats(cls) -> None:
@@ -229,6 +264,226 @@ class AgentRunStats:
229
264
  return " | ".join(parts)
230
265
 
231
266
 
267
+ # ---------------------------------------------------------------------------
268
+ # High output-mode per-turn stats rendering
269
+ # ---------------------------------------------------------------------------
270
+
271
+
272
+ # Line threshold above which an informational footer is shown in high mode.
273
+ # This is NOT a truncation gate — high mode always shows the full result.
274
+ _HIGH_MODE_RESULT_FOOTER_THRESHOLD = 50
275
+
276
+
277
+ # Tool names whose response has already been rendered inline (streamed or
278
+ # via display_non_streamed_result) and should NOT be dumped again.
279
+ _ALREADY_RENDERED_TOOLS = frozenset({"invoke_agent", "invoke_agent_with_model"})
280
+
281
+ # Tools whose output is already rendered by the rich_renderer via MessageBus
282
+ # messages (FileContentMessage, DiffMessage, GrepResultMessage, etc.).
283
+ # High-mode metadata annotations are already shown inline by the renderer,
284
+ # so dumping the tool result body again would be noisy redundancy.
285
+ _TOOLS_WITH_RENDERER = frozenset(
286
+ {
287
+ "read_file",
288
+ "list_files",
289
+ "grep",
290
+ "create_file",
291
+ "replace_in_file",
292
+ "delete_file",
293
+ "delete_snippet",
294
+ "edit_file",
295
+ "agent_run_shell_command",
296
+ "ask_user_question",
297
+ "activate_skill",
298
+ "list_or_search_skills",
299
+ "agent_share_your_reasoning",
300
+ "universal_constructor",
301
+ "load_image_for_analysis",
302
+ }
303
+ )
304
+
305
+
306
+ def _stringify_result(result: Any) -> str:
307
+ """Convert a tool result to a human-readable multi-line string.
308
+
309
+ Handles structured types (Pydantic BaseModel, dataclass, dict, list)
310
+ that produce single-line repr strings with escaped newlines when
311
+ passed through ``str()``.
312
+ """
313
+ if isinstance(result, str):
314
+ return result
315
+
316
+ # Pydantic BaseModel -> JSON-like dict
317
+ if hasattr(result, "model_dump"):
318
+ try:
319
+ import json
320
+
321
+ return json.dumps(result.model_dump(), indent=2, default=str)
322
+ except Exception:
323
+ pass
324
+
325
+ # dataclass -> JSON-like dict
326
+ import dataclasses
327
+
328
+ if dataclasses.is_dataclass(result) and not isinstance(result, type):
329
+ try:
330
+ import json
331
+
332
+ return json.dumps(dataclasses.asdict(result), indent=2, default=str)
333
+ except Exception:
334
+ pass
335
+
336
+ # dict / list -> JSON
337
+ if isinstance(result, (dict, list)):
338
+ try:
339
+ import json
340
+
341
+ return json.dumps(result, indent=2, default=str)
342
+ except Exception:
343
+ pass
344
+
345
+ # Last resort: str() with escaped-newline recovery.
346
+ text = str(result)
347
+ if "\\n" in text and "\n" not in text:
348
+ text = text.replace("\\n", "\n")
349
+ return text
350
+
351
+
352
+ def _render_high_mode_tool_result(
353
+ tool_name: str,
354
+ tool_args: Any,
355
+ result: Any,
356
+ duration_ms: float,
357
+ ) -> None:
358
+ """Print a tool-result summary when ``output_level`` is ``high``.
359
+
360
+ Shows the return value that gets sent back to the model, truncated to
361
+ keep the terminal readable. Medium mode is unaffected.
362
+ """
363
+ try:
364
+ from code_puppy.config import get_output_level
365
+
366
+ if get_output_level() != "high":
367
+ return
368
+
369
+ from rich.markup import escape as _esc
370
+
371
+ from code_puppy.agents.event_stream_handler import get_streaming_console
372
+
373
+ console = get_streaming_console()
374
+ dur_str = f"{duration_ms:.0f}" if duration_ms >= 1 else f"{duration_ms:.1f}"
375
+
376
+ # Sub-agent results: the response body was already streamed or
377
+ # rendered by display_non_streamed_result. Dumping the raw repr
378
+ # of AgentInvokeOutput would produce a single unreadable line
379
+ # with escaped newlines. Show a compact summary instead.
380
+ if tool_name in _ALREADY_RENDERED_TOOLS:
381
+ _render_high_mode_agent_result(console, tool_name, result, dur_str)
382
+ return
383
+
384
+ # Tools whose output was already rendered by the rich_renderer:
385
+ # show a compact duration-only line to avoid double-rendering.
386
+ if tool_name in _TOOLS_WITH_RENDERER:
387
+ console.print(
388
+ f"[dim] \u21a9 {_esc(tool_name)} returned ({dur_str} ms)[/dim]"
389
+ )
390
+ return
391
+
392
+ # General path: convert structured results to readable multi-line
393
+ # text (handles Pydantic models, dataclasses, dicts, lists).
394
+ # High mode shows the FULL result — no truncation. The user
395
+ # explicitly opted into maximum verbosity.
396
+ result_str = _stringify_result(result)
397
+ lines = result_str.splitlines()
398
+ total_lines = len(lines)
399
+ total_chars = len(result_str)
400
+
401
+ console.print(f"[dim] \u21a9 {_esc(tool_name)} returned ({dur_str} ms):[/dim]")
402
+ for line in lines:
403
+ console.print(f"[dim] {_esc(line)}[/dim]")
404
+ if total_lines > _HIGH_MODE_RESULT_FOOTER_THRESHOLD:
405
+ console.print(
406
+ f"[dim] ({total_lines} lines, ~{total_chars:,} chars)[/dim]"
407
+ )
408
+ except Exception:
409
+ pass # never crash for cosmetic output
410
+
411
+
412
+ def _render_high_mode_agent_result(
413
+ console: Any,
414
+ tool_name: str,
415
+ result: Any,
416
+ dur_str: str,
417
+ ) -> None:
418
+ """Compact one-liner for invoke_agent / invoke_agent_with_model results."""
419
+ from rich.markup import escape as _esc
420
+
421
+ agent_name = getattr(result, "agent_name", None) or "?"
422
+ error = getattr(result, "error", None)
423
+ response = getattr(result, "response", None)
424
+
425
+ if error:
426
+ console.print(
427
+ f"[dim] \u21a9 {_esc(tool_name)} returned ({dur_str} ms): "
428
+ f"[red]FAIL[/red] {_esc(agent_name)}[/dim]"
429
+ )
430
+ elif response is not None:
431
+ char_count = len(response)
432
+ console.print(
433
+ f"[dim] \u21a9 {_esc(tool_name)} returned ({dur_str} ms): "
434
+ f"[green]OK[/green] {_esc(agent_name)} ({char_count:,} chars)[/dim]"
435
+ )
436
+ else:
437
+ console.print(
438
+ f"[dim] \u21a9 {_esc(tool_name)} returned ({dur_str} ms): "
439
+ f"{_esc(agent_name)} (no response)[/dim]"
440
+ )
441
+
442
+
443
+ def _render_high_mode_stats() -> None:
444
+ """Print a per-turn stats line when ``output_level`` is ``high``.
445
+
446
+ Reads the just-snapshotted cycle data from :class:`AgentRunStats` and
447
+ renders a compact dim line below the response showing model name,
448
+ TTFT, generation latency, and token counts.
449
+ """
450
+ try:
451
+ from code_puppy.config import get_output_level
452
+
453
+ if get_output_level() != "high":
454
+ return
455
+
456
+ stats = AgentRunStats.get_last_cycle_stats()
457
+ # Only render if we actually have timing data.
458
+ if stats["ttft_seconds"] <= 0 and stats["gen_seconds"] <= 0:
459
+ return
460
+
461
+ from code_puppy.agents.event_stream_handler import get_streaming_console
462
+
463
+ console = get_streaming_console()
464
+
465
+ parts: list[str] = []
466
+
467
+ if stats["ttft_seconds"] > 0:
468
+ parts.append(f"TTFT {stats['ttft_seconds']:.2f} s")
469
+
470
+ if stats["gen_seconds"] > 0:
471
+ parts.append(f"gen {stats['gen_seconds']:.1f} s")
472
+
473
+ if stats["gen_tps"] > 0:
474
+ parts.append(f"{stats['gen_tps']:,.1f} t/s")
475
+
476
+ if stats["output_tokens"] > 0:
477
+ parts.append(f"~{stats['output_tokens']:,} output tokens (est)")
478
+
479
+ if parts:
480
+ line = " | ".join(parts)
481
+ console.print(f"\n[dim] {line}[/dim]")
482
+ except Exception:
483
+ # Never crash the app for cosmetic stats rendering.
484
+ pass
485
+
486
+
232
487
  # ---------------------------------------------------------------------------
233
488
  # Callback handlers
234
489
  # ---------------------------------------------------------------------------
@@ -255,7 +510,7 @@ async def _on_agent_run_start(
255
510
  """Mark T0 = true request-start, before any HTTP packets fly."""
256
511
  if is_subagent():
257
512
  return
258
- AgentRunStats.mark_request_start()
513
+ AgentRunStats.mark_request_start(model_name=model_name)
259
514
 
260
515
 
261
516
  async def _on_stream_event(
@@ -287,6 +542,17 @@ async def _on_stream_event(
287
542
  _record_text_tokens(args)
288
543
 
289
544
 
545
+ async def _on_post_tool_call(
546
+ tool_name: str,
547
+ tool_args: Any,
548
+ result: Any,
549
+ duration_ms: float,
550
+ context: Any = None,
551
+ ) -> None:
552
+ """Render the tool return value inline in ``high`` output mode."""
553
+ _render_high_mode_tool_result(tool_name, tool_args, result, duration_ms)
554
+
555
+
290
556
  async def _on_agent_run_end(
291
557
  agent_name: str,
292
558
  model_name: str,
@@ -300,10 +566,14 @@ async def _on_agent_run_end(
300
566
 
301
567
  Always fires regardless of success/failure so partial-but-real stats
302
568
  still count toward the running averages.
569
+
570
+ In ``high`` output mode, a per-turn stats line is printed to the
571
+ streaming console so the user sees timing + token data inline.
303
572
  """
304
573
  if is_subagent():
305
574
  return
306
575
  AgentRunStats.snapshot_cycle_into_aggregates()
576
+ _render_high_mode_stats()
307
577
 
308
578
 
309
579
  # ---------------------------------------------------------------------------
@@ -313,7 +583,7 @@ _HOOKS_REGISTERED = False
313
583
 
314
584
 
315
585
  def register_hooks() -> None:
316
- """Idempotently register the three run-stats callback hooks."""
586
+ """Idempotently register the run-stats callback hooks."""
317
587
  global _HOOKS_REGISTERED
318
588
  if _HOOKS_REGISTERED:
319
589
  return
@@ -323,6 +593,7 @@ def register_hooks() -> None:
323
593
  register_callback("agent_run_start", _on_agent_run_start)
324
594
  register_callback("stream_event", _on_stream_event)
325
595
  register_callback("agent_run_end", _on_agent_run_end)
596
+ register_callback("post_tool_call", _on_post_tool_call)
326
597
  _HOOKS_REGISTERED = True
327
598
  except Exception:
328
599
  # Callback module unavailable (extremely unlikely); silently skip
@@ -341,4 +612,5 @@ __all__ = [
341
612
  "_on_agent_run_start",
342
613
  "_on_stream_event",
343
614
  "_on_agent_run_end",
615
+ "_on_post_tool_call",
344
616
  ]
@@ -46,6 +46,7 @@ from code_puppy.config import (
46
46
  get_openai_reasoning_effort,
47
47
  get_openai_reasoning_summary,
48
48
  get_openai_verbosity,
49
+ get_output_level,
49
50
  get_owner_name,
50
51
  get_pack_agents_enabled,
51
52
  get_protected_token_count,
@@ -489,6 +490,19 @@ _SAFETY = SettingsCategory(
489
490
  _OUTPUT = SettingsCategory(
490
491
  name="Output",
491
492
  settings=(
493
+ Setting(
494
+ key="output_level",
495
+ display_name="Output Level",
496
+ description=(
497
+ "Unified density control for conversation output. "
498
+ "low = one-line peeks for tool calls & thinking, "
499
+ "medium = current default, "
500
+ "high = full metadata with timing, tokens, and verbose output."
501
+ ),
502
+ type_hint="choice",
503
+ valid_values=("low", "medium", "high"),
504
+ effective_getter=get_output_level,
505
+ ),
492
506
  Setting(
493
507
  key="smooth_response_stream",
494
508
  display_name="Smooth Response Stream",
@@ -2015,6 +2015,51 @@ def set_suppress_informational_messages(enabled: bool):
2015
2015
  set_config_value("suppress_informational_messages", "true" if enabled else "false")
2016
2016
 
2017
2017
 
2018
+ # ---------------------------------------------------------------------------
2019
+ # Output level (unified density control)
2020
+ # ---------------------------------------------------------------------------
2021
+
2022
+ _VALID_OUTPUT_LEVELS = frozenset({"low", "medium", "high"})
2023
+
2024
+
2025
+ def get_output_level() -> str:
2026
+ """Return the current output density level.
2027
+
2028
+ Valid values: ``low``, ``medium``, ``high``. Default is ``medium``
2029
+ (current behaviour). The value is read from ``puppy.cfg`` with the
2030
+ key ``output_level``.
2031
+
2032
+ * **low** — collapse tool calls, thinking blocks, and info messages
2033
+ to one-line peeks. Great for focused work.
2034
+ * **medium** — current default behaviour.
2035
+ * **high** — full metadata: timing, tokens, verbose grep, all
2036
+ sub-agent output.
2037
+ """
2038
+ cfg_val = get_value("output_level")
2039
+ if cfg_val is not None:
2040
+ normalised = str(cfg_val).strip().lower()
2041
+ if normalised in _VALID_OUTPUT_LEVELS:
2042
+ return normalised
2043
+ return "medium"
2044
+
2045
+
2046
+ def set_output_level(level: str) -> None:
2047
+ """Set the output density level.
2048
+
2049
+ Args:
2050
+ level: One of ``low``, ``medium``, or ``high``.
2051
+
2052
+ Raises:
2053
+ ValueError: If *level* is not a valid choice.
2054
+ """
2055
+ normalised = level.strip().lower()
2056
+ if normalised not in _VALID_OUTPUT_LEVELS:
2057
+ raise ValueError(
2058
+ f"Invalid output_level {level!r}; choose from low, medium, high"
2059
+ )
2060
+ set_config_value("output_level", normalised)
2061
+
2062
+
2018
2063
  # API Key management functions
2019
2064
  def get_api_key(key_name: str) -> str:
2020
2065
  """Get an API key from puppy.cfg.