code-puppy 0.0.618__tar.gz → 0.0.620__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 (457) hide show
  1. {code_puppy-0.0.618 → code_puppy-0.0.620}/PKG-INFO +2 -1
  2. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/agents/_runtime.py +11 -2
  3. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/agents/agent_manager.py +36 -5
  4. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/agents/json_agent.py +1 -1
  5. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/callbacks.py +64 -11
  6. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/config.py +19 -0
  7. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/mcp_/manager.py +11 -0
  8. code_puppy-0.0.620/code_puppy/plugins/acp/README.md +266 -0
  9. code_puppy-0.0.620/code_puppy/plugins/acp/__init__.py +8 -0
  10. code_puppy-0.0.620/code_puppy/plugins/acp/agent.py +456 -0
  11. code_puppy-0.0.620/code_puppy/plugins/acp/bridge.py +311 -0
  12. code_puppy-0.0.620/code_puppy/plugins/acp/capabilities.py +73 -0
  13. code_puppy-0.0.620/code_puppy/plugins/acp/commands.py +116 -0
  14. code_puppy-0.0.620/code_puppy/plugins/acp/content.py +115 -0
  15. code_puppy-0.0.620/code_puppy/plugins/acp/io_delegation.py +231 -0
  16. code_puppy-0.0.620/code_puppy/plugins/acp/mcp_config.py +66 -0
  17. code_puppy-0.0.620/code_puppy/plugins/acp/permissions.py +160 -0
  18. code_puppy-0.0.620/code_puppy/plugins/acp/persistence.py +197 -0
  19. code_puppy-0.0.620/code_puppy/plugins/acp/register_callbacks.py +110 -0
  20. code_puppy-0.0.620/code_puppy/plugins/acp/replay.py +114 -0
  21. code_puppy-0.0.620/code_puppy/plugins/acp/session.py +294 -0
  22. code_puppy-0.0.620/code_puppy/plugins/acp/session_config.py +180 -0
  23. code_puppy-0.0.620/code_puppy/plugins/acp/state.py +137 -0
  24. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/config.py +43 -1
  25. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/file_permission_handler/register_callbacks.py +141 -4
  26. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/plugin_list/plugins_menu.py +30 -3
  27. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/plugin_list/plugins_menu_render.py +14 -1
  28. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/tools/agent_tools.py +1 -1
  29. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/tools/ask_user_question/tui_loop.py +33 -0
  30. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/tools/command_runner.py +67 -2
  31. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/tools/common.py +149 -4
  32. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/tools/file_modifications.py +283 -70
  33. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/tools/file_operations.py +425 -91
  34. code_puppy-0.0.620/code_puppy/tools/fs_access.py +229 -0
  35. code_puppy-0.0.620/code_puppy/tools/io_backends.py +186 -0
  36. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/tools/subagent_context.py +37 -0
  37. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/undo_manager.py +14 -8
  38. {code_puppy-0.0.618 → code_puppy-0.0.620}/pyproject.toml +2 -1
  39. {code_puppy-0.0.618 → code_puppy-0.0.620}/.gitignore +0 -0
  40. {code_puppy-0.0.618 → code_puppy-0.0.620}/LICENSE +0 -0
  41. {code_puppy-0.0.618 → code_puppy-0.0.620}/README.md +0 -0
  42. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/__init__.py +0 -0
  43. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/__main__.py +0 -0
  44. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/agents/__init__.py +0 -0
  45. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/agents/_builder.py +0 -0
  46. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/agents/_compaction.py +0 -0
  47. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/agents/_diagnostics.py +0 -0
  48. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/agents/_history.py +0 -0
  49. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/agents/_key_listeners.py +0 -0
  50. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/agents/_non_streaming_render.py +0 -0
  51. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/agents/_run_signals.py +0 -0
  52. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/agents/_steer_processor.py +0 -0
  53. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/agents/agent_code_puppy.py +0 -0
  54. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/agents/agent_creator_agent.py +0 -0
  55. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/agents/agent_helios.py +0 -0
  56. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/agents/agent_planning.py +0 -0
  57. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/agents/agent_qa_kitten.py +0 -0
  58. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/agents/base_agent.py +0 -0
  59. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/agents/event_stream_handler.py +0 -0
  60. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/agents/run_stats.py +0 -0
  61. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/agents/smooth_stream.py +0 -0
  62. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/agents/subagent_stream_handler.py +0 -0
  63. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/chatgpt_codex_client.py +0 -0
  64. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/claude_cache_client.py +0 -0
  65. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/cli_runner.py +0 -0
  66. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/__init__.py +0 -0
  67. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/add_model_menu.py +0 -0
  68. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/agent_menu.py +0 -0
  69. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/attachments.py +0 -0
  70. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/autosave_menu.py +0 -0
  71. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/autosave_search.py +0 -0
  72. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/clipboard.py +0 -0
  73. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/colors_menu.py +0 -0
  74. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/command_handler.py +0 -0
  75. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/command_registry.py +0 -0
  76. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/config_apply.py +0 -0
  77. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/config_commands.py +0 -0
  78. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/core_commands.py +0 -0
  79. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/diff_menu.py +0 -0
  80. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/file_index.py +0 -0
  81. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/file_path_completion.py +0 -0
  82. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/judges_menu.py +0 -0
  83. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/load_context_completion.py +0 -0
  84. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/mcp/__init__.py +0 -0
  85. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/mcp/base.py +0 -0
  86. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/mcp/catalog_server_installer.py +0 -0
  87. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/mcp/custom_server_form.py +0 -0
  88. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/mcp/custom_server_installer.py +0 -0
  89. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/mcp/edit_command.py +0 -0
  90. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/mcp/handler.py +0 -0
  91. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/mcp/help_command.py +0 -0
  92. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/mcp/install_command.py +0 -0
  93. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/mcp/install_menu.py +0 -0
  94. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/mcp/list_command.py +0 -0
  95. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/mcp/logs_command.py +0 -0
  96. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/mcp/remove_command.py +0 -0
  97. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/mcp/restart_command.py +0 -0
  98. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/mcp/search_command.py +0 -0
  99. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/mcp/silence_warning_command.py +0 -0
  100. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/mcp/start_all_command.py +0 -0
  101. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/mcp/start_command.py +0 -0
  102. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/mcp/status_command.py +0 -0
  103. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/mcp/stop_all_command.py +0 -0
  104. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/mcp/stop_command.py +0 -0
  105. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/mcp/utils.py +0 -0
  106. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/mcp/wizard_utils.py +0 -0
  107. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/mcp_binding_menu.py +0 -0
  108. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/mcp_completion.py +0 -0
  109. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/model_picker_completion.py +0 -0
  110. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/model_settings_menu.py +0 -0
  111. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/onboarding_slides.py +0 -0
  112. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/onboarding_wizard.py +0 -0
  113. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/pagination.py +0 -0
  114. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/pin_command_completion.py +0 -0
  115. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/prompt_toolkit_completion.py +0 -0
  116. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/session_commands.py +0 -0
  117. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/set_menu.py +0 -0
  118. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/set_menu_catalog.py +0 -0
  119. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/set_menu_render.py +0 -0
  120. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/set_menu_schema.py +0 -0
  121. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/set_menu_settings.py +0 -0
  122. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/set_menu_shims.py +0 -0
  123. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/set_menu_values.py +0 -0
  124. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/shell_passthrough.py +0 -0
  125. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/skills_completion.py +0 -0
  126. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/uc_menu.py +0 -0
  127. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/utils.py +0 -0
  128. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/command_line/wiggum_state.py +0 -0
  129. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/error_logging.py +0 -0
  130. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/gemini_code_assist.py +0 -0
  131. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/gemini_model.py +0 -0
  132. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/hook_engine/README.md +0 -0
  133. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/hook_engine/__init__.py +0 -0
  134. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/hook_engine/aliases.py +0 -0
  135. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/hook_engine/engine.py +0 -0
  136. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/hook_engine/executor.py +0 -0
  137. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/hook_engine/matcher.py +0 -0
  138. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/hook_engine/models.py +0 -0
  139. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/hook_engine/registry.py +0 -0
  140. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/hook_engine/validator.py +0 -0
  141. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/http_utils.py +0 -0
  142. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/keymap.py +0 -0
  143. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/list_filtering.py +0 -0
  144. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/main.py +0 -0
  145. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/mcp_/__init__.py +0 -0
  146. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/mcp_/agent_bindings.py +0 -0
  147. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/mcp_/async_lifecycle.py +0 -0
  148. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/mcp_/blocking_startup.py +0 -0
  149. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/mcp_/captured_stdio_server.py +0 -0
  150. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/mcp_/circuit_breaker.py +0 -0
  151. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/mcp_/config_wizard.py +0 -0
  152. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/mcp_/dashboard.py +0 -0
  153. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/mcp_/error_isolation.py +0 -0
  154. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/mcp_/examples/retry_example.py +0 -0
  155. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/mcp_/health_monitor.py +0 -0
  156. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/mcp_/managed_server.py +0 -0
  157. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/mcp_/mcp_logs.py +0 -0
  158. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/mcp_/registry.py +0 -0
  159. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/mcp_/retry_manager.py +0 -0
  160. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/mcp_/server_registry_catalog.py +0 -0
  161. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/mcp_/status_tracker.py +0 -0
  162. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/mcp_/system_tools.py +0 -0
  163. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/mcp_/tool_arg_coercion.py +0 -0
  164. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/mcp_prompts/__init__.py +0 -0
  165. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/mcp_prompts/hook_creator.py +0 -0
  166. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/messaging/__init__.py +0 -0
  167. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/messaging/bar_painters.py +0 -0
  168. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/messaging/bar_rendering.py +0 -0
  169. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/messaging/bottom_bar.py +0 -0
  170. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/messaging/bus.py +0 -0
  171. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/messaging/chords.py +0 -0
  172. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/messaging/commands.py +0 -0
  173. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/messaging/editor_actions.py +0 -0
  174. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/messaging/editor_completion.py +0 -0
  175. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/messaging/editor_display.py +0 -0
  176. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/messaging/editor_history.py +0 -0
  177. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/messaging/editor_keys.py +0 -0
  178. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/messaging/editor_paste.py +0 -0
  179. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/messaging/external_editor.py +0 -0
  180. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/messaging/line_editor.py +0 -0
  181. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/messaging/markdown_patches.py +0 -0
  182. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/messaging/message_queue.py +0 -0
  183. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/messaging/messages.py +0 -0
  184. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/messaging/pause_controller.py +0 -0
  185. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/messaging/prompt_prefix_style.py +0 -0
  186. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/messaging/queue_console.py +0 -0
  187. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/messaging/renderers.py +0 -0
  188. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/messaging/rich_renderer.py +0 -0
  189. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/messaging/run_ui.py +0 -0
  190. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/messaging/run_ui_wiring.py +0 -0
  191. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/messaging/spinner/__init__.py +0 -0
  192. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/messaging/subagent_console.py +0 -0
  193. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/messaging/transcript_guard.py +0 -0
  194. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/model_descriptions.py +0 -0
  195. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/model_factory.py +0 -0
  196. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/model_switching.py +0 -0
  197. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/model_utils.py +0 -0
  198. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/models.json +0 -0
  199. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/models_dev_api.json +0 -0
  200. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/models_dev_parser.py +0 -0
  201. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/__init__.py +0 -0
  202. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/agent_skills/__init__.py +0 -0
  203. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/agent_skills/config.py +0 -0
  204. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/agent_skills/discovery.py +0 -0
  205. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/agent_skills/downloader.py +0 -0
  206. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/agent_skills/enabled_skills.py +0 -0
  207. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/agent_skills/installer.py +0 -0
  208. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/agent_skills/metadata.py +0 -0
  209. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/agent_skills/prompt_builder.py +0 -0
  210. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/agent_skills/register_callbacks.py +0 -0
  211. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/agent_skills/remote_catalog.py +0 -0
  212. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/agent_skills/skill_catalog.py +0 -0
  213. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/agent_skills/skill_commands.py +0 -0
  214. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/agent_skills/skills_install_menu.py +0 -0
  215. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/agent_skills/skills_menu.py +0 -0
  216. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/aws_bedrock/__init__.py +0 -0
  217. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/aws_bedrock/config.py +0 -0
  218. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/aws_bedrock/register_callbacks.py +0 -0
  219. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/aws_bedrock/utils.py +0 -0
  220. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/azure_foundry/README.md +0 -0
  221. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/azure_foundry/__init__.py +0 -0
  222. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/azure_foundry/config.py +0 -0
  223. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/azure_foundry/discovery.py +0 -0
  224. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/azure_foundry/register_callbacks.py +0 -0
  225. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/azure_foundry/token.py +0 -0
  226. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/azure_foundry/utils.py +0 -0
  227. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/btw/__init__.py +0 -0
  228. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/btw/inline_view.py +0 -0
  229. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/btw/register_callbacks.py +0 -0
  230. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/btw/side_query.py +0 -0
  231. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/chatgpt_oauth/__init__.py +0 -0
  232. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/chatgpt_oauth/config.py +0 -0
  233. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/chatgpt_oauth/oauth_flow.py +0 -0
  234. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/chatgpt_oauth/register_callbacks.py +0 -0
  235. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/chatgpt_oauth/test_plugin.py +0 -0
  236. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/chatgpt_oauth/utils.py +0 -0
  237. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/claude_code_hooks/__init__.py +0 -0
  238. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/claude_code_hooks/config.py +0 -0
  239. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/claude_code_hooks/register_callbacks.py +0 -0
  240. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/claude_code_oauth/README.md +0 -0
  241. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/claude_code_oauth/SETUP.md +0 -0
  242. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/claude_code_oauth/__init__.py +0 -0
  243. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/claude_code_oauth/config.py +0 -0
  244. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/claude_code_oauth/fast_mode.py +0 -0
  245. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/claude_code_oauth/prompt_handler.py +0 -0
  246. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/claude_code_oauth/register_callbacks.py +0 -0
  247. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/claude_code_oauth/test_fast_mode.py +0 -0
  248. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/claude_code_oauth/test_plugin.py +0 -0
  249. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/claude_code_oauth/token_refresh_heartbeat.py +0 -0
  250. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/claude_code_oauth/utils.py +0 -0
  251. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/code_puppy_agent/SKILL.md +0 -0
  252. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/code_puppy_agent/__init__.py +0 -0
  253. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/code_puppy_agent/register_callbacks.py +0 -0
  254. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/context_indicator/__init__.py +0 -0
  255. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/context_indicator/register_callbacks.py +0 -0
  256. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/context_indicator/usage.py +0 -0
  257. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/copilot_auth/__init__.py +0 -0
  258. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/copilot_auth/config.py +0 -0
  259. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/copilot_auth/reasoning_client.py +0 -0
  260. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/copilot_auth/register_callbacks.py +0 -0
  261. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/copilot_auth/utils.py +0 -0
  262. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/customizable_commands/__init__.py +0 -0
  263. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/customizable_commands/register_callbacks.py +0 -0
  264. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/dbos_durable_exec/__init__.py +0 -0
  265. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/dbos_durable_exec/cancel.py +0 -0
  266. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/dbos_durable_exec/commands.py +0 -0
  267. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/dbos_durable_exec/config.py +0 -0
  268. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/dbos_durable_exec/lifecycle.py +0 -0
  269. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/dbos_durable_exec/register_callbacks.py +0 -0
  270. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/dbos_durable_exec/runtime.py +0 -0
  271. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/dbos_durable_exec/startup_lock.py +0 -0
  272. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/dbos_durable_exec/workflow_ids.py +0 -0
  273. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/dbos_durable_exec/wrapper.py +0 -0
  274. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/destructive_command_guard/__init__.py +0 -0
  275. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/destructive_command_guard/detector.py +0 -0
  276. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/destructive_command_guard/register_callbacks.py +0 -0
  277. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/emoji_filter/__init__.py +0 -0
  278. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/emoji_filter/config.py +0 -0
  279. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/emoji_filter/register_callbacks.py +0 -0
  280. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/emoji_filter/stripper.py +0 -0
  281. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/empty_html_comment_filter/register_callbacks.py +0 -0
  282. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/example_custom_command/README.md +0 -0
  283. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/example_custom_command/register_callbacks.py +0 -0
  284. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/file_permission_handler/__init__.py +0 -0
  285. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/force_push_guard/__init__.py +0 -0
  286. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/force_push_guard/detector.py +0 -0
  287. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/force_push_guard/register_callbacks.py +0 -0
  288. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/force_push_guard/test_detector.py +0 -0
  289. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/fork/__init__.py +0 -0
  290. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/fork/register_callbacks.py +0 -0
  291. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/frontend_emitter/__init__.py +0 -0
  292. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/frontend_emitter/emitter.py +0 -0
  293. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/frontend_emitter/register_callbacks.py +0 -0
  294. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/frontend_emitter/session_context.py +0 -0
  295. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/grok_oauth/__init__.py +0 -0
  296. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/grok_oauth/config.py +0 -0
  297. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/grok_oauth/oauth_flow.py +0 -0
  298. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/grok_oauth/register_callbacks.py +0 -0
  299. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/grok_oauth/test_plugin.py +0 -0
  300. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/grok_oauth/utils.py +0 -0
  301. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/herdr/README.md +0 -0
  302. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/herdr/__init__.py +0 -0
  303. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/herdr/client.py +0 -0
  304. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/herdr/register_callbacks.py +0 -0
  305. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/herdr/reporter.py +0 -0
  306. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/hook_creator/__init__.py +0 -0
  307. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/hook_creator/register_callbacks.py +0 -0
  308. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/hook_manager/__init__.py +0 -0
  309. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/hook_manager/config.py +0 -0
  310. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/hook_manager/hooks_menu.py +0 -0
  311. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/hook_manager/register_callbacks.py +0 -0
  312. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/no_tools/__init__.py +0 -0
  313. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/no_tools/register_callbacks.py +0 -0
  314. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/oauth_puppy_html.py +0 -0
  315. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/obsidian_agent/README.md +0 -0
  316. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/obsidian_agent/__init__.py +0 -0
  317. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/obsidian_agent/agent_obsidian.py +0 -0
  318. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/obsidian_agent/register_callbacks.py +0 -0
  319. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/ollama/__init__.py +0 -0
  320. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/ollama/register_callbacks.py +0 -0
  321. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/ollama_setup/__init__.py +0 -0
  322. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/ollama_setup/completer.py +0 -0
  323. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/ollama_setup/register_callbacks.py +0 -0
  324. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/plugin_list/__init__.py +0 -0
  325. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/plugin_list/plugin_contributions.py +0 -0
  326. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/plugin_list/plugin_meta.py +0 -0
  327. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/plugin_list/plugin_text_utils.py +0 -0
  328. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/plugin_list/plugins_menu_layout.py +0 -0
  329. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/plugin_list/project_trust_flow.py +0 -0
  330. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/plugin_list/register_callbacks.py +0 -0
  331. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/pop_command/__init__.py +0 -0
  332. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/pop_command/register_callbacks.py +0 -0
  333. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/prompt_newline/__init__.py +0 -0
  334. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/prompt_newline/config.py +0 -0
  335. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/prompt_newline/register_callbacks.py +0 -0
  336. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/prune/__init__.py +0 -0
  337. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/prune/prune_menu.py +0 -0
  338. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/prune/prune_model.py +0 -0
  339. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/prune/prune_render.py +0 -0
  340. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/prune/register_callbacks.py +0 -0
  341. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/puppy_kennel/README.md +0 -0
  342. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/puppy_kennel/__init__.py +0 -0
  343. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/puppy_kennel/commands.py +0 -0
  344. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/puppy_kennel/config.py +0 -0
  345. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/puppy_kennel/kennel.py +0 -0
  346. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/puppy_kennel/packer.py +0 -0
  347. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/puppy_kennel/recorder.py +0 -0
  348. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/puppy_kennel/register_callbacks.py +0 -0
  349. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/puppy_kennel/retriever.py +0 -0
  350. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/puppy_kennel/schema.py +0 -0
  351. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/puppy_kennel/state.py +0 -0
  352. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/puppy_kennel/tools.py +0 -0
  353. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/puppy_kennel/wings.py +0 -0
  354. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/puppy_spinner/README.md +0 -0
  355. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/puppy_spinner/__init__.py +0 -0
  356. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/puppy_spinner/builtin_frames.py +0 -0
  357. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/puppy_spinner/commands.py +0 -0
  358. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/puppy_spinner/picker.py +0 -0
  359. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/puppy_spinner/register_callbacks.py +0 -0
  360. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/puppy_spinner/spinners.py +0 -0
  361. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/quick_resume/__init__.py +0 -0
  362. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/quick_resume/register_callbacks.py +0 -0
  363. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/review_pr/__init__.py +0 -0
  364. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/review_pr/register_callbacks.py +0 -0
  365. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/shell_safety/__init__.py +0 -0
  366. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/shell_safety/agent_shell_safety.py +0 -0
  367. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/shell_safety/command_cache.py +0 -0
  368. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/shell_safety/register_callbacks.py +0 -0
  369. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/stack_dump/__init__.py +0 -0
  370. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/stack_dump/register_callbacks.py +0 -0
  371. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/statusline/__init__.py +0 -0
  372. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/statusline/config.py +0 -0
  373. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/statusline/payload.py +0 -0
  374. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/statusline/prompt_patch.py +0 -0
  375. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/statusline/register_callbacks.py +0 -0
  376. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/statusline/runner.py +0 -0
  377. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/statusline/statusline_command.py +0 -0
  378. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/steer_queue/__init__.py +0 -0
  379. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/steer_queue/queue_menu.py +0 -0
  380. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/steer_queue/register_callbacks.py +0 -0
  381. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/subagent_panel/README.md +0 -0
  382. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/subagent_panel/__init__.py +0 -0
  383. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/subagent_panel/coalesce_patch.py +0 -0
  384. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/subagent_panel/panel_render.py +0 -0
  385. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/subagent_panel/register_callbacks.py +0 -0
  386. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/subagent_panel/resume_repaint.py +0 -0
  387. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/subagent_panel/state.py +0 -0
  388. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/switch_agent_resume/__init__.py +0 -0
  389. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/switch_agent_resume/register_callbacks.py +0 -0
  390. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/theme/README.md +0 -0
  391. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/theme/__init__.py +0 -0
  392. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/theme/bundled_palettes.py +0 -0
  393. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/theme/content_styles.py +0 -0
  394. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/theme/osc_palette.py +0 -0
  395. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/theme/picker.py +0 -0
  396. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/theme/register_callbacks.py +0 -0
  397. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/theme/rich_themes.py +0 -0
  398. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/theme/themes.py +0 -0
  399. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/token_ratio_learner/__init__.py +0 -0
  400. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/token_ratio_learner/ratios.py +0 -0
  401. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/token_ratio_learner/register_callbacks.py +0 -0
  402. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/trust.py +0 -0
  403. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/trust_notice.py +0 -0
  404. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/universal_constructor/__init__.py +0 -0
  405. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/universal_constructor/models.py +0 -0
  406. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/universal_constructor/register_callbacks.py +0 -0
  407. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/universal_constructor/registry.py +0 -0
  408. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/universal_constructor/sandbox.py +0 -0
  409. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/wide_completion_menu/__init__.py +0 -0
  410. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/wide_completion_menu/register_callbacks.py +0 -0
  411. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/wiggum/__init__.py +0 -0
  412. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/wiggum/judge.py +0 -0
  413. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/wiggum/judge_config.py +0 -0
  414. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/wiggum/register_callbacks.py +0 -0
  415. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/plugins/wiggum/state.py +0 -0
  416. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/provider_credentials.py +0 -0
  417. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/provider_identity.py +0 -0
  418. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/pydantic_patches.py +0 -0
  419. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/reopenable_async_client.py +0 -0
  420. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/round_robin_model.py +0 -0
  421. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/session_lifecycle.py +0 -0
  422. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/session_migration.py +0 -0
  423. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/session_storage.py +0 -0
  424. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/status_display.py +0 -0
  425. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/summarization_agent.py +0 -0
  426. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/terminal_utils.py +0 -0
  427. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/tools/__init__.py +0 -0
  428. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/tools/ask_user_question/__init__.py +0 -0
  429. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/tools/ask_user_question/constants.py +0 -0
  430. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/tools/ask_user_question/demo_tui.py +0 -0
  431. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/tools/ask_user_question/handler.py +0 -0
  432. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/tools/ask_user_question/models.py +0 -0
  433. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/tools/ask_user_question/registration.py +0 -0
  434. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/tools/ask_user_question/renderers.py +0 -0
  435. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/tools/ask_user_question/terminal_ui.py +0 -0
  436. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/tools/ask_user_question/theme.py +0 -0
  437. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/tools/browser/__init__.py +0 -0
  438. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/tools/browser/browser_control.py +0 -0
  439. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/tools/browser/browser_interactions.py +0 -0
  440. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/tools/browser/browser_locator_resolver.py +0 -0
  441. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/tools/browser/browser_locators.py +0 -0
  442. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/tools/browser/browser_manager.py +0 -0
  443. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/tools/browser/browser_navigation.py +0 -0
  444. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/tools/browser/browser_page_snapshot.py +0 -0
  445. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/tools/browser/browser_screenshot.py +0 -0
  446. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/tools/browser/browser_scripts.py +0 -0
  447. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/tools/browser/browser_semantic_interactions.py +0 -0
  448. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/tools/browser/browser_workflows.py +0 -0
  449. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/tools/display.py +0 -0
  450. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/tools/image_tools.py +0 -0
  451. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/tools/model_tools.py +0 -0
  452. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/tools/shell_backgrounding.py +0 -0
  453. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/tools/skills_tools.py +0 -0
  454. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/tools/subagent_invocation.py +0 -0
  455. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/tools/tools_content.py +0 -0
  456. {code_puppy-0.0.618 → code_puppy-0.0.620}/code_puppy/tools/universal_constructor.py +0 -0
  457. {code_puppy-0.0.618 → code_puppy-0.0.620}/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.618
3
+ Version: 0.0.620
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
@@ -15,6 +15,7 @@ Classifier: Programming Language :: Python :: 3.12
15
15
  Classifier: Programming Language :: Python :: 3.13
16
16
  Classifier: Topic :: Software Development :: Code Generators
17
17
  Requires-Python: <3.15,>=3.11
18
+ Requires-Dist: agent-client-protocol<0.12,>=0.11.0
18
19
  Requires-Dist: anthropic==0.79.0
19
20
  Requires-Dist: azure-identity>=1.15.0
20
21
  Requires-Dist: boto3>=1.43.9
@@ -815,10 +815,19 @@ async def _run_with_mcp_impl(
815
815
  # console clamp on Windows), ^C arrives as \x03 and the key
816
816
  # listener handles cancellation. SIGINT only fires out-of-band
817
817
  # (kill -INT, piped stdin with no listener, cooked-mode gaps
818
- # between raw readers) the handler installed here is that
818
+ # between raw readers) -- the handler installed here is that
819
819
  # fallback: it cancels when ^C IS the cancel gesture, and only
820
820
  # hints at the real key when cancel is remapped.
821
- if sigint_fallback_cancels():
821
+ #
822
+ # Off the main thread (ACP server, embeds, worker threads) we skip
823
+ # SIGINT wiring entirely: signal handlers are main-thread-only in
824
+ # CPython, so installing one there raises "signal only works in
825
+ # main thread". Cancellation still flows through
826
+ # schedule_agent_cancel, and the stdin key listener no-ops when
827
+ # stdin isn't a TTY, so no cancel affordance is lost.
828
+ if threading.current_thread() is not threading.main_thread():
829
+ pass # original_handler stays None -> restore is a no-op
830
+ elif sigint_fallback_cancels():
822
831
  original_handler = signal.signal(
823
832
  signal.SIGINT, keyboard_interrupt_handler
824
833
  )
@@ -71,8 +71,16 @@ def _is_process_alive(pid: int) -> bool:
71
71
  pid: Process ID to check
72
72
 
73
73
  Returns:
74
- bool: True if process likely exists, False otherwise
74
+ bool: True if process likely exists, False otherwise.
75
75
  """
76
+ try:
77
+ process_id = int(pid)
78
+ except (TypeError, ValueError, OverflowError):
79
+ return False
80
+
81
+ if process_id <= 0:
82
+ return False
83
+
76
84
  try:
77
85
  if os.name == "nt":
78
86
  # Windows: use OpenProcess to probe liveness safely
@@ -88,7 +96,7 @@ def _is_process_alive(pid: int) -> bool:
88
96
  ]
89
97
  kernel32.OpenProcess.restype = wintypes.HANDLE
90
98
  handle = kernel32.OpenProcess(
91
- PROCESS_QUERY_LIMITED_INFORMATION, False, int(pid)
99
+ PROCESS_QUERY_LIMITED_INFORMATION, False, process_id
92
100
  )
93
101
  if handle:
94
102
  kernel32.CloseHandle(handle)
@@ -101,7 +109,7 @@ def _is_process_alive(pid: int) -> bool:
101
109
  return False
102
110
  else:
103
111
  # Unix-like: signal 0 does not deliver a signal but checks existence
104
- os.kill(int(pid), 0)
112
+ os.kill(process_id, 0)
105
113
  return True
106
114
  except PermissionError:
107
115
  # No permission to signal -> process exists
@@ -182,8 +190,31 @@ def _save_session_data(sessions: dict[str, str]) -> None:
182
190
  with open(temp_file, "w", encoding="utf-8") as f:
183
191
  json.dump(cleaned_sessions, f, indent=2)
184
192
 
185
- # Atomic rename (works on all platforms)
186
- temp_file.replace(session_file)
193
+ # Atomic rename; on Windows replace() is best-effort if target exists
194
+ try:
195
+ temp_file.replace(session_file)
196
+ except Exception:
197
+ try:
198
+ if session_file.exists():
199
+ session_file.unlink(
200
+ missing_ok=True
201
+ ) # Python 3.8+: ignore if missing
202
+ except Exception:
203
+ pass
204
+ try:
205
+ temp_file.replace(session_file)
206
+ except Exception:
207
+ # As a last resort, copy contents
208
+ try:
209
+ with (
210
+ open(temp_file, "r", encoding="utf-8") as rf,
211
+ open(session_file, "w", encoding="utf-8") as wf,
212
+ ):
213
+ wf.write(rf.read())
214
+ temp_file.unlink(missing_ok=True)
215
+ except Exception:
216
+ # Give up silently; session persistence isn't critical
217
+ pass
187
218
 
188
219
  except (IOError, OSError):
189
220
  # File permission issues, etc. - just continue without persistence
@@ -209,7 +209,7 @@ class JSONAgent(BaseAgent):
209
209
  return override
210
210
 
211
211
  result = self._config.get("model")
212
- if result is None:
212
+ if result is None or (isinstance(result, str) and not result.strip()):
213
213
  result = super().get_model_name()
214
214
  return result
215
215
 
@@ -15,6 +15,7 @@ PhaseType = Literal[
15
15
  "delete_snippet",
16
16
  "delete_file",
17
17
  "run_shell_command",
18
+ "run_shell_command_output",
18
19
  "load_model_config",
19
20
  "load_models_config",
20
21
  "load_model_descriptions",
@@ -55,6 +56,7 @@ PhaseType = Literal[
55
56
  "user_prompt_submit",
56
57
  "pre_compact",
57
58
  "session_end",
59
+ "post_autosave",
58
60
  "notification",
59
61
  ]
60
62
  CallbackFunc = Callable[..., Any]
@@ -71,6 +73,7 @@ _callbacks: Dict[PhaseType, List[CallbackFunc]] = {
71
73
  "delete_snippet": [],
72
74
  "delete_file": [],
73
75
  "run_shell_command": [],
76
+ "run_shell_command_output": [],
74
77
  "load_model_config": [],
75
78
  "load_models_config": [],
76
79
  "load_model_descriptions": [],
@@ -111,6 +114,7 @@ _callbacks: Dict[PhaseType, List[CallbackFunc]] = {
111
114
  "user_prompt_submit": [],
112
115
  "pre_compact": [],
113
116
  "session_end": [],
117
+ "post_autosave": [],
114
118
  "notification": [],
115
119
  }
116
120
 
@@ -318,8 +322,8 @@ async def on_startup() -> List[Any]:
318
322
  return await _trigger_callbacks("startup")
319
323
 
320
324
 
321
- async def on_shutdown() -> List[Any]:
322
- return await _trigger_callbacks("shutdown")
325
+ def on_shutdown() -> List[Any]:
326
+ return _trigger_callbacks_sync("shutdown")
323
327
 
324
328
 
325
329
  async def on_invoke_agent(*args, **kwargs) -> List[Any]:
@@ -388,10 +392,24 @@ async def on_run_shell_command(*args, **kwargs) -> Any:
388
392
  return await _trigger_callbacks("run_shell_command", *args, **kwargs)
389
393
 
390
394
 
395
+ async def on_run_shell_command_output(*args, **kwargs) -> Any:
396
+ return await _trigger_callbacks("run_shell_command_output", *args, **kwargs)
397
+
398
+
391
399
  def on_agent_reload(*args, **kwargs) -> Any:
392
400
  return _trigger_callbacks_sync("agent_reload", *args, **kwargs)
393
401
 
394
402
 
403
+ async def on_post_autosave(*args, **kwargs) -> List[Any]:
404
+ """Fire after an auto-save successfully writes a session.
405
+
406
+ Receives the autosave ``SessionMetadata`` so plugins can render
407
+ follow-up info lines (e.g. remaining token quota) without having
408
+ to reach back into the autosave plumbing themselves.
409
+ """
410
+ return await _trigger_callbacks("post_autosave", *args, **kwargs)
411
+
412
+
395
413
  def on_load_prompt():
396
414
  """Collect load_prompt fragments from plugins, dropping ``None`` results.
397
415
 
@@ -440,10 +458,13 @@ def on_file_permission(
440
458
  message_group: str | None = None,
441
459
  operation_data: Any = None,
442
460
  ) -> List[Any]:
443
- """Trigger file permission callbacks.
461
+ """Trigger file permission callbacks synchronously.
444
462
 
445
- This allows plugins to register handlers for file permission checks
446
- before file operations are performed.
463
+ This preserves the original sync ``file_permission`` hook contract for
464
+ terminal/CLI plugins. If a callback is async and no event loop is running,
465
+ it is executed with ``asyncio.run`` by ``_trigger_callbacks_sync``. If an
466
+ event loop is already running, callers that need async callbacks to be
467
+ awaited should use :func:`on_file_permission_async` instead.
447
468
 
448
469
  Args:
449
470
  context: The operation context
@@ -454,8 +475,8 @@ def on_file_permission(
454
475
  operation_data: Operation-specific data for preview generation (recommended)
455
476
 
456
477
  Returns:
457
- List of boolean results from permission handlers.
458
- Returns True if permission should be granted, False if denied.
478
+ List of permission results. Callers should treat explicit ``False`` as
479
+ denial, ``True`` as approval, and ``None`` as no opinion.
459
480
  """
460
481
  # For backward compatibility, if operation_data is provided, prefer it over preview
461
482
  if operation_data is not None:
@@ -471,6 +492,38 @@ def on_file_permission(
471
492
  )
472
493
 
473
494
 
495
+ async def on_file_permission_async(
496
+ context: Any,
497
+ file_path: str,
498
+ operation: str,
499
+ preview: str | None = None,
500
+ message_group: str | None = None,
501
+ operation_data: Any = None,
502
+ ) -> List[Any]:
503
+ """Trigger file permission callbacks from async tool execution.
504
+
505
+ This uses the existing ``file_permission`` hook phase and awaits async
506
+ callbacks while still supporting sync callbacks unchanged. It is intended
507
+ for async file tools, including WebSocket/browser approval flows, where the
508
+ tool must wait for a permission decision without dropping an unawaited
509
+ coroutine. Sync callbacks still run inline, matching existing behavior.
510
+
511
+ Return semantics match :func:`on_file_permission`: explicit ``False``
512
+ denies, ``True`` approves, and ``None`` means no opinion.
513
+ """
514
+ if operation_data is not None:
515
+ preview = None
516
+ return await _trigger_callbacks(
517
+ "file_permission",
518
+ context,
519
+ file_path,
520
+ operation,
521
+ preview,
522
+ message_group,
523
+ operation_data,
524
+ )
525
+
526
+
474
527
  async def on_pre_tool_call(
475
528
  tool_name: str, tool_args: dict, context: Any = None
476
529
  ) -> List[Any]:
@@ -963,17 +1016,17 @@ def on_register_browser_types() -> List[Any]:
963
1016
 
964
1017
  Plugins can register callbacks that return a dict mapping browser type names
965
1018
  to initialization functions. This allows plugins to provide custom browser
966
- implementations (like Camoufox for stealth browsing).
1019
+ implementations (such as stealth-focused or hardened browsers).
967
1020
 
968
1021
  Each callback should return a dict with:
969
- - key: str - the browser type name (e.g., "camoufox", "firefox-stealth")
1022
+ - key: str - the browser type name (e.g., "firefox-stealth", "hardened")
970
1023
  - value: callable - async initialization function that takes (manager, **kwargs)
971
1024
  and sets up the browser on the manager instance
972
1025
 
973
1026
  Example callback:
974
1027
  def register_my_browser_types():
975
1028
  return {
976
- "camoufox": initialize_camoufox,
1029
+ "firefox-stealth": initialize_firefox_stealth,
977
1030
  "my-stealth-browser": initialize_my_stealth,
978
1031
  }
979
1032
 
@@ -987,7 +1040,7 @@ def on_register_model_providers() -> List[Any]:
987
1040
  """Trigger callbacks to register custom model provider classes.
988
1041
 
989
1042
  Plugins can register callbacks that return a dict mapping provider names
990
- to model classes. Example: {"walmart_gemini": WalmartGeminiModel}
1043
+ to model classes. Example: {"my_provider": MyCustomModel}
991
1044
 
992
1045
  Returns:
993
1046
  List of dicts from all registered callbacks.
@@ -1419,6 +1419,25 @@ def get_message_limit(default: int = 1000) -> int:
1419
1419
  return default
1420
1420
 
1421
1421
 
1422
+ def get_command_timeout_seconds() -> int:
1423
+ """
1424
+ Returns the user-configured absolute timeout for shell commands in seconds.
1425
+ This is the maximum time any single command can run before being terminated.
1426
+ Defaults to 270 seconds if unset or misconfigured.
1427
+ Valid range: 60-900 seconds. Values outside this range default to 270.
1428
+ Configurable by 'command_timeout_seconds' key.
1429
+ """
1430
+ val = get_value("command_timeout_seconds")
1431
+ try:
1432
+ timeout = int(val) if val else 270
1433
+ # Enforce bounds: min 60, max 900, default 270 if outside bounds
1434
+ if timeout < 60 or timeout > 900:
1435
+ return 270
1436
+ return timeout
1437
+ except (ValueError, TypeError):
1438
+ return 270
1439
+
1440
+
1422
1441
  def save_command_to_history(command: str):
1423
1442
  """Save a command to the history file with an ISO format timestamp.
1424
1443
 
@@ -174,6 +174,17 @@ class MCPManager:
174
174
 
175
175
  for name, conf in configs.items():
176
176
  try:
177
+ # The config loader is the single chokepoint for wrapper-key
178
+ # normalization (it accepts both mcp_servers and mcpServers
179
+ # and never returns wrapper keys as server names). Sync only
180
+ # guards against per-entry garbage.
181
+ if not isinstance(conf, dict):
182
+ logger.warning(
183
+ "Skipping MCP server '%s': config must be a dictionary",
184
+ name,
185
+ )
186
+ continue
187
+
177
188
  # Create ServerConfig from the loaded configuration
178
189
  server_config = ServerConfig(
179
190
  id=conf.get("id", ""), # Empty ID will be auto-generated
@@ -0,0 +1,266 @@
1
+ # `acp` — Code Puppy as a native ACP agent
2
+
3
+ Run Code Puppy inside any ACP-capable editor's agent panel (e.g.
4
+ [Zed](https://github.com/zed-industries/zed))
5
+ by speaking the **Agent Client Protocol (ACP)** — the same JSON-RPC-over-stdio
6
+ protocol these editors use to host Gemini CLI and Claude Code.
7
+
8
+ This plugin is built on the **official [`agent-client-protocol`](https://pypi.org/project/agent-client-protocol/)
9
+ Python SDK** (`acp`). The SDK owns the wire — stdio binding, JSON-RPC framing,
10
+ typed Pydantic models, and the bidirectional connection — so this plugin is
11
+ pure *behaviour*: mapping ACP sessions to Code Puppy agents, translating
12
+ runtime events into `session/update`s, and routing Code Puppy's I/O + approval
13
+ edges to the client.
14
+
15
+ > **Status:** live over real stdio. Implemented: `initialize`, `session/new`,
16
+ > `session/load` (replays persisted history), `session/prompt`,
17
+ > `session/cancel` (also kills local shells), `session/list`, `session/close`,
18
+ > `session/fork` (duplicates history), `session/resume` (rehydrates across
19
+ restarts), `session/set_mode`, `session/set_config_option`. Assistant text +
20
+ > thinking stream as `agent_message_chunk` / `agent_thought_chunk`; tool calls
21
+ > stream as `tool_call` / `tool_call_update` (with `kind`, file `locations`,
22
+ > friendly titles, and inline diffs); slash commands are advertised via
23
+ > `available_commands_update` **and executed** when the client sends one. Prompt
24
+ > turns report token usage; **image** input is accepted. Client-injected MCP
25
+ > servers and multi-root `additionalDirectories` are honoured. Workspace file
26
+ > I/O and shell delegate to the client (capability-gated), and **permissions**
27
+ > for file writes and shell commands are surfaced in the client's own allow/deny
28
+ > dialog in non-yolo mode.
29
+ >
30
+ > Not implemented: `elicitation/*` (the SDK's connection API exposes no
31
+ > elicitation call in 0.10.1), `plan` updates (Code Puppy has no plan model),
32
+ > and the unstable `document/*` / `nes/*` / `providers/*` surface.
33
+
34
+ ---
35
+
36
+ ## How the client hosts an external agent
37
+
38
+ 1. The client launches the agent as a **subprocess** and talks JSON-RPC 2.0 over the
39
+ process's **stdin/stdout** (stderr is free for logging).
40
+ 2. The agent advertises what it can do in an `initialize` handshake; the client
41
+ advertises what *it* can do (read/write files, run terminals, permissions).
42
+ 3. The client drives with `session/new` then `session/prompt`; the agent streams
43
+ progress back with `session/update` notifications and can call *back into
44
+ the client* for file I/O, terminals, and permission prompts.
45
+
46
+ This is a **bidirectional** JSON-RPC connection: both sides send requests.
47
+
48
+ ### Registering us in a client
49
+
50
+ Registration is client-specific. Example — Zed's `settings.json`:
51
+
52
+ ```jsonc
53
+ {
54
+ "agent_servers": {
55
+ "Code Puppy": { "command": "code-puppy", "args": ["--acp"], "env": {} }
56
+ }
57
+ }
58
+ ```
59
+
60
+ Then "Code Puppy" appears in the agent panel's "New Thread" menu.
61
+
62
+ ---
63
+
64
+ ## Why the official SDK
65
+
66
+ We adopted `agent-client-protocol` instead of hand-rolling JSON-RPC because it
67
+ gives us, maintained and spec-accurate:
68
+
69
+ * **Typed models** for the entire protocol (`InitializeResponse`,
70
+ `SessionNotification`, all content/capability/tool-call types).
71
+ * **`acp.run_agent(agent)`** — binds stdio, frames ndjson JSON-RPC, parses
72
+ params into models, dispatches to our `Agent`, and hands us a `Client`
73
+ connection for talking back.
74
+ * **Update builders** (`update_agent_message_text`, `start_tool_call`, …).
75
+
76
+ Net effect: ~400 lines of hand-rolled transport/framing/capability code
77
+ deleted, correct-by-construction wire behaviour, and a PR that speaks the
78
+ project's own library. Our two small **core seams stay unchanged** — only the
79
+ plugin's protocol layer changed.
80
+
81
+ ---
82
+
83
+ ## Design decisions (locked in)
84
+
85
+ | Decision | Choice |
86
+ |----------|--------|
87
+ | **Protocol layer** | **Official `acp` SDK.** We implement its `Agent` interface; `acp.run_agent` owns stdio + framing. |
88
+ | **Who does I/O** | **Delegated to the client when the client supports it.** Workspace file reads/writes go through the client's `fs/read_text_file` / `fs/write_text_file` (edits land in the client's diff UI; reads see unsaved buffers), and shell commands run via the client's `terminal/*`. This rides two small, general **I/O-backend seams** in core (`code_puppy/tools/io_backends.py`): a sync `FileSystemBackend` and an async `CommandExecutor`, both `None` by default (local I/O) and installed by this plugin, capability-gated, after `initialize`. Internal writes (config, session state, agent metadata) deliberately stay local — only *workspace* edits reroute (via `common.write_project_file`). |
89
+ | **Permissions** | **the client is the authority (non-yolo).** Every approval — file writes and shell commands — is surfaced in the client's own allow/deny dialog via `session/request_permission`. No yolo forcing, no terminal prompts. |
90
+ | **Entry point** | A `--acp` CLI flag contributed via the `register_cli_args` hook; `handle_cli_args` boots the agent (on its own loop, in a thread) and short-circuits normal TUI startup. |
91
+ | **Core footprint** | Small, general, additive core seams — **no monkeypatching**: (1) a pluggable *approval backend* (`common.set_approval_backend`), (2) a *workspace write* wrapper (`common.write_project_file`) + backend-aware `_read_file`, and (3) `FileSystemBackend` / `CommandExecutor` registries (`tools/io_backends.py`). Each is useful to any non-terminal embedder, not ACP-specific. Everything else is this plugin + existing public hooks + the SDK. |
92
+
93
+ ### Permissions in non-yolo mode (the important part)
94
+
95
+ Code Puppy has two approval edges. In a headless ACP server there is no TTY, so
96
+ the built-in stdin prompt would **fail closed** (auto-deny every file op — a
97
+ latent bug this integration also fixes). We route both edges to the client *without*
98
+ forcing yolo and *without* patching tool logic:
99
+
100
+ * **File operations** use the **approval-backend seam** in `tools.common`. Sync
101
+ file tools run in Code Puppy's tool threadpool, so the backend
102
+ (`permissions.py`) bridges to the ACP event loop with
103
+ `run_coroutine_threadsafe` to ask the client via the SDK's `request_permission`,
104
+ then blocks the worker thread for the answer. The loop is free to service the
105
+ round-trip → no deadlock (guarded against being called on the loop itself).
106
+ * **Shell commands** use the async `run_shell_command` hook (it runs on the ACP
107
+ loop and can `await` the client directly).
108
+
109
+ Both edges **fail closed** if the connection drops or the client errors.
110
+
111
+ ---
112
+
113
+ ## Module layout
114
+
115
+ Every file stays well under the 600-line cap and owns one concern.
116
+
117
+ | File | Responsibility |
118
+ |------|----------------|
119
+ | `register_callbacks.py` | Register the `--acp` flag; when present, redirect the console to stderr, run `acp.run_agent(CodePuppyAgent())` on its own loop in a thread, and return `{"handled": True}` so the TUI never starts. |
120
+ | `agent.py` | `CodePuppyAgent(acp.Agent)` — the SDK agent implementation: initialize, new/load/resume/fork/list/close session, prompt, cancel, set_session_mode/model, set_config_option, authenticate, plus `on_connect` (stashes the client handle + installs approvals). |
121
+ | `capabilities.py` | Declarative capability negotiation in SDK models: our `AgentCapabilities`, and parsing the client's `ClientCapabilities` into `(fs_read, fs_write, terminal)`. |
122
+ | `content.py` | Parse ACP prompt content blocks → text + multimodal attachments (`BinaryContent` / `ImageUrl`), honouring `embeddedContext` + `image`. |
123
+ | `session.py` | `ACPSession`: one ACP session ⇄ one `BaseAgent` + its `_message_history`. Runs each turn as a cancellable `asyncio.Task`; persists history after each turn; owns the final-result fallback. |
124
+ | `commands.py` | Execute client-typed `/slash` commands via `command_handler`, capturing MessageBus output and forwarding it (never touches stdin). |
125
+ | `persistence.py` | Pickle each session's history under `AUTOSAVE_DIR/acp` keyed by session id, plus an ACP metadata sidecar (`cwd` + `additionalDirectories` + title). Rehydrate on `load`/`resume`/`fork`; enumerate for `session/list` (`list_persisted`); tombstone on `session/close` (`delete`). |
126
+ | `replay.py` | On `load`/`resume`, stream the rehydrated history back to the client as ordered `session/update`s (user / agent text / thinking / past tool calls) so the client rebuilds the thread UI. |
127
+ | `mcp_config.py` | Translate client-injected ACP MCP server specs → pydantic-ai servers on the session agent. |
128
+ | `session_config.py` | Build the model list (surfaced as ACP *modes*) + safe config options; apply `set_mode` / `set_config_option`. |
129
+ | `bridge.py` | `EventBridge`: registers `stream_event` / `pre_tool_call` / `post_tool_call` hooks and translates them into SDK `session/update`s via `connection.session_update`. (Hooks, **not** MessageBus — see *Event source*.) |
130
+ | `permissions.py` | Wires Code Puppy's two approval edges to the client via the SDK's `request_permission`: the `tools.common` approval backend (files, cross-thread) and the `run_shell_command` hook (shell). Fails closed. |
131
+ | `io_delegation.py` | `DelegatedFileSystemBackend` (sync, cross-thread) + `DelegatedCommandExecutor` (async terminal lifecycle) that plug into the core I/O seams, capability-gated. |
132
+ | `state.py` | Process-wide run context: the SDK connection + its loop, the active session id, and the open-tool-call stack — so the permission/I/O seams (plain module functions) can reach the running connection and correlate events. |
133
+
134
+ ```
135
+ Client ──stdin──▶ acp.run_agent ──▶ CodePuppyAgent.prompt ──▶ ACPSession ──▶ agent.run_with_mcp
136
+
137
+ stream_event / pre_tool_call / post_tool_call hooks fire ─────┘
138
+
139
+
140
+ bridge ──▶ connection.session_update ──stdout──▶ the client
141
+
142
+ │ agent needs to read/write/run/ask
143
+ └── permissions / io_delegation ──▶ connection.{request_permission,
144
+ read_text_file, write_text_file, create_terminal, …} ──▶ the client
145
+ ```
146
+
147
+ ### Event source: hooks, not the MessageBus
148
+
149
+ Code Puppy's `MessageBus` is **single-consumer** and *buffers* until a renderer
150
+ attaches; agent text streams through pydantic-ai's `event_stream_handler`
151
+ (which fires the `stream_event` callback), not the bus. So the bridge taps the
152
+ **callback hooks** — the same seam the shipping `frontend_emitter` plugin uses:
153
+
154
+ | Hook | Fires with | ACP update |
155
+ |------|-----------|------------|
156
+ | `stream_event` (`part_delta`, `TextPartDelta`) | `event_data.delta.content_delta` | `agent_message_chunk` |
157
+ | `stream_event` (`part_delta`, `ThinkingPartDelta`) | `event_data.delta.content_delta` | `agent_thought_chunk` |
158
+ | `pre_tool_call` | `tool_name`, `tool_args` | `tool_call` (status `in_progress`) |
159
+ | `post_tool_call` | `tool_name`, `result` | `tool_call_update` (status `completed`/`failed`) |
160
+
161
+ Run context (active session id, whether text streamed, the open-tool-call
162
+ stack) lives in `state`, so `bridge`, `permissions`, and `io_delegation` share
163
+ one source of truth. `set_session_context(session_id)` is also set around each
164
+ run so streamed events carry the right session id.
165
+
166
+ ### stdout is sacred
167
+
168
+ ACP speaks JSON-RPC on **stdout**, so nothing else may write there. At boot we
169
+ point the streaming console (`set_streaming_console`) and the root logger at
170
+ **stderr**; the interactive path that normally configures the console is
171
+ short-circuited in `--acp` mode.
172
+
173
+ ### Streaming-off fallback
174
+
175
+ `use_streaming` is config-gated. When off, no `stream_event` deltas fire, so the
176
+ session sends the return value of `run_with_mcp` as a single final
177
+ `agent_message_chunk`. `state` tracks whether any text streamed so we never
178
+ double-send.
179
+
180
+ ---
181
+
182
+ ## ACP surface we implement
183
+
184
+ ### Inbound (the client → us)
185
+
186
+ | Method | Behaviour |
187
+ |--------|-----------|
188
+ | `initialize` | Negotiate version + capabilities; install capability-gated I/O delegation. |
189
+ | `authenticate` / `logout` | No-op (auth is via Code Puppy's own model config/env). |
190
+ | `session/new` | Create an `ACPSession` (fresh `BaseAgent`) from `cwd` + `additionalDirectories`; attach client `mcpServers`; return models + config options; schedule `available_commands_update`. |
191
+ | `session/load` | Re-open a thread: **replay persisted history into the agent AND stream it back to the client** as `session/update`s so the client rebuilds the thread UI. |
192
+ | `session/resume` | Rehydrate + replay a session across a restart from persisted history. |
193
+ | `session/fork` | Branch a session: copy its history into a new id. Works on a live session **or** one persisted by a prior process (rehydrated from disk), so forking survives a restart. |
194
+ | `session/prompt` | Parse content blocks (text + image attachments) or execute a `/slash` command; run the agent as a cancellable task; stream updates; return stop reason **+ token usage**. |
195
+ | `session/cancel` | Cancel the in-flight run's task **and kill local shells** → `cancelled`. |
196
+ | `session/list` / `session/close` | List sessions (**live in-memory + persisted on disk**, deduped, so threads survive a restart and stay revivable) / drop a session (also deletes its persisted copy). |
197
+ | `session/set_mode` | Switch the active model, rebinding the session agent (history preserved). Code Puppy surfaces its model list as ACP *modes* (0.11 removed the separate models API). |
198
+ | `session/set_config_option` | Apply a safe config change (streaming toggle); never yolo. |
199
+ | `session/set_mode` | No-op (Code Puppy has one mode). |
200
+
201
+ Not implemented: `elicitation/*` (the SDK connection exposes no elicitation
202
+ call in 0.10.1), `plan` updates (no native plan model), and the unstable
203
+ `document/*` / `nes/*` / `providers/*` surface. The SDK router resolves any
204
+ unimplemented method to a clean "method not found", so we advertise honestly
205
+ and stub nothing.
206
+
207
+ ### Outbound notifications (us → the client) — `session/update`
208
+
209
+ `agent_message_chunk`, `agent_thought_chunk`, `tool_call`, `tool_call_update`,
210
+ `available_commands_update`. Tool calls carry human-friendly titles
211
+ ("Edit foo.py", "Run: pytest"), a `kind`, file `locations`, and — on completion
212
+ — the unified diff as an inline `diff` content block so edits are visible in
213
+ the client's tool-call entry.
214
+
215
+ ### Outbound requests (us → the client)
216
+
217
+ `session/request_permission` (approvals), and — when the client advertises the
218
+ capability — `fs/read_text_file`, `fs/write_text_file`, and the `terminal/*`
219
+ family (`create`, `wait_for_exit`, `output`, `kill`, `release`).
220
+
221
+ ---
222
+
223
+ ## Session & history model
224
+
225
+ - One ACP session id ⇄ one `ACPSession` ⇄ one `BaseAgent` instance.
226
+ - Multi-turn is native: `_message_history` persists across `session/prompt`
227
+ calls within the same session.
228
+ - `cwd` from `session/new` anchors that session's tools.
229
+
230
+ ---
231
+
232
+ ## Interactive tools (`ask_user_question`)
233
+
234
+ Code Puppy's `ask_user_question` renders a terminal picker and reads stdin —
235
+ neither is available over ACP (stdin *is* the JSON-RPC pipe). The tool's own
236
+ `isatty()` guard already makes it fail closed there (no stdout corruption), but
237
+ the default "not an interactive terminal" error is a dead end.
238
+
239
+ So in ACP mode the `EventBridge` **blocks** `ask_user_question` at the
240
+ `pre_tool_call` seam (before any tool-call entry is opened) and returns guidance
241
+ steering the model to *ask the user directly in its normal text response* — which
242
+ the client renders as a regular assistant message the user can reply to. This is
243
+ the pragmatic stand-in until ACP ratifies structured **elicitation** (currently
244
+ only an [RFD](https://agentclientprotocol.com), not in stable v1 — no client,
245
+ including Zed, implements it yet). When elicitation lands and the SDK exposes a
246
+ connection method for it, this block becomes a real native picker.
247
+
248
+ ---
249
+
250
+ ## Testing
251
+
252
+ `tests/test_acp_plugin.py` drives `CodePuppyAgent` directly against a fake SDK
253
+ connection (no real stdio) and covers:
254
+
255
+ - capability negotiation + client-cap parsing,
256
+ - content-block flattening (incl. embedded resources),
257
+ - lifecycle: initialize / new_session / prompt (stream + fallback) / cancel /
258
+ list / close / unknown-session error,
259
+ - tool-call `kind` / `locations` / pre↔post correlation,
260
+ - the core approval-backend seam (sync + async) + the shell hook,
261
+ - the **cross-thread approval bridge** (worker thread → ACP loop → the client → back),
262
+ - I/O delegation core seams + the client fs/terminal backends (capability-gated).
263
+
264
+ Real end-to-end: `code-puppy --acp` spawned as a subprocess answers
265
+ `initialize` + `session/new` with clean JSON-RPC on stdout. Manual: point a
266
+ real client at `code-puppy --acp` via `agent_servers`.
@@ -0,0 +1,8 @@
1
+ """Code Puppy as a native Agent Client Protocol (ACP) agent.
2
+
3
+ This plugin lets Code Puppy run as an external agent inside the client's agent
4
+ panel by speaking the Agent Client Protocol (ACP) — JSON-RPC 2.0 over
5
+ stdio. See ``README.md`` in this directory for the full design.
6
+
7
+ Boot it with ``code-puppy --acp`` (the client does this for you once configured).
8
+ """