code-puppy-core-plugins 0.0.2__py3-none-any.whl

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 (313) hide show
  1. code_puppy_core_plugins/__init__.py +5 -0
  2. code_puppy_core_plugins/acp/README.md +266 -0
  3. code_puppy_core_plugins/acp/__init__.py +8 -0
  4. code_puppy_core_plugins/acp/agent.py +494 -0
  5. code_puppy_core_plugins/acp/bridge.py +309 -0
  6. code_puppy_core_plugins/acp/capabilities.py +73 -0
  7. code_puppy_core_plugins/acp/commands.py +116 -0
  8. code_puppy_core_plugins/acp/content.py +115 -0
  9. code_puppy_core_plugins/acp/io_delegation.py +231 -0
  10. code_puppy_core_plugins/acp/mcp_config.py +66 -0
  11. code_puppy_core_plugins/acp/permissions.py +159 -0
  12. code_puppy_core_plugins/acp/persistence.py +197 -0
  13. code_puppy_core_plugins/acp/register_callbacks.py +110 -0
  14. code_puppy_core_plugins/acp/replay.py +114 -0
  15. code_puppy_core_plugins/acp/session.py +329 -0
  16. code_puppy_core_plugins/acp/session_config.py +179 -0
  17. code_puppy_core_plugins/acp/state.py +135 -0
  18. code_puppy_core_plugins/agent_skills/__init__.py +22 -0
  19. code_puppy_core_plugins/agent_skills/config.py +208 -0
  20. code_puppy_core_plugins/agent_skills/discovery.py +337 -0
  21. code_puppy_core_plugins/agent_skills/downloader.py +392 -0
  22. code_puppy_core_plugins/agent_skills/enabled_skills.py +82 -0
  23. code_puppy_core_plugins/agent_skills/installer.py +22 -0
  24. code_puppy_core_plugins/agent_skills/metadata.py +219 -0
  25. code_puppy_core_plugins/agent_skills/prompt_builder.py +49 -0
  26. code_puppy_core_plugins/agent_skills/provider.py +52 -0
  27. code_puppy_core_plugins/agent_skills/register_callbacks.py +309 -0
  28. code_puppy_core_plugins/agent_skills/remote_catalog.py +322 -0
  29. code_puppy_core_plugins/agent_skills/skill_catalog.py +257 -0
  30. code_puppy_core_plugins/agent_skills/skill_commands.py +102 -0
  31. code_puppy_core_plugins/agent_skills/skills_install_menu.py +698 -0
  32. code_puppy_core_plugins/agent_skills/skills_menu.py +794 -0
  33. code_puppy_core_plugins/aws_bedrock/__init__.py +14 -0
  34. code_puppy_core_plugins/aws_bedrock/config.py +101 -0
  35. code_puppy_core_plugins/aws_bedrock/register_callbacks.py +243 -0
  36. code_puppy_core_plugins/aws_bedrock/utils.py +186 -0
  37. code_puppy_core_plugins/azure_foundry/README.md +238 -0
  38. code_puppy_core_plugins/azure_foundry/__init__.py +15 -0
  39. code_puppy_core_plugins/azure_foundry/config.py +126 -0
  40. code_puppy_core_plugins/azure_foundry/discovery.py +189 -0
  41. code_puppy_core_plugins/azure_foundry/register_callbacks.py +506 -0
  42. code_puppy_core_plugins/azure_foundry/token.py +182 -0
  43. code_puppy_core_plugins/azure_foundry/utils.py +375 -0
  44. code_puppy_core_plugins/btw/__init__.py +1 -0
  45. code_puppy_core_plugins/btw/inline_view.py +135 -0
  46. code_puppy_core_plugins/btw/register_callbacks.py +106 -0
  47. code_puppy_core_plugins/btw/side_query.py +91 -0
  48. code_puppy_core_plugins/chatgpt_oauth/IMAGEGEN_SKILL.md +83 -0
  49. code_puppy_core_plugins/chatgpt_oauth/__init__.py +8 -0
  50. code_puppy_core_plugins/chatgpt_oauth/config.py +52 -0
  51. code_puppy_core_plugins/chatgpt_oauth/image_generation.py +253 -0
  52. code_puppy_core_plugins/chatgpt_oauth/image_tool.py +70 -0
  53. code_puppy_core_plugins/chatgpt_oauth/oauth_flow.py +461 -0
  54. code_puppy_core_plugins/chatgpt_oauth/register_callbacks.py +288 -0
  55. code_puppy_core_plugins/chatgpt_oauth/test_plugin.py +663 -0
  56. code_puppy_core_plugins/chatgpt_oauth/usage.py +113 -0
  57. code_puppy_core_plugins/chatgpt_oauth/utils.py +534 -0
  58. code_puppy_core_plugins/claude_code_hooks/__init__.py +1 -0
  59. code_puppy_core_plugins/claude_code_hooks/config.py +137 -0
  60. code_puppy_core_plugins/claude_code_hooks/register_callbacks.py +383 -0
  61. code_puppy_core_plugins/claude_code_oauth/README.md +167 -0
  62. code_puppy_core_plugins/claude_code_oauth/SETUP.md +93 -0
  63. code_puppy_core_plugins/claude_code_oauth/__init__.py +25 -0
  64. code_puppy_core_plugins/claude_code_oauth/config.py +59 -0
  65. code_puppy_core_plugins/claude_code_oauth/fast_mode.py +122 -0
  66. code_puppy_core_plugins/claude_code_oauth/prompt_handler.py +64 -0
  67. code_puppy_core_plugins/claude_code_oauth/register_callbacks.py +719 -0
  68. code_puppy_core_plugins/claude_code_oauth/test_plugin.py +285 -0
  69. code_puppy_core_plugins/claude_code_oauth/token_refresh_heartbeat.py +240 -0
  70. code_puppy_core_plugins/claude_code_oauth/utils.py +663 -0
  71. code_puppy_core_plugins/code_puppy_agent/AGENTS_AND_TOOLS.md +155 -0
  72. code_puppy_core_plugins/code_puppy_agent/MODELS_AND_MCP.md +104 -0
  73. code_puppy_core_plugins/code_puppy_agent/PLUGINS_AND_CALLBACKS.md +147 -0
  74. code_puppy_core_plugins/code_puppy_agent/SESSIONS_AND_HISTORY.md +39 -0
  75. code_puppy_core_plugins/code_puppy_agent/SKILL.md +180 -0
  76. code_puppy_core_plugins/code_puppy_agent/SKILLS_SYSTEM.md +136 -0
  77. code_puppy_core_plugins/code_puppy_agent/SYSTEM_PROMPT_CONFIG_AND_I18N.md +160 -0
  78. code_puppy_core_plugins/code_puppy_agent/__init__.py +5 -0
  79. code_puppy_core_plugins/code_puppy_agent/register_callbacks.py +46 -0
  80. code_puppy_core_plugins/computer_use/NativeCapture.swift +123 -0
  81. code_puppy_core_plugins/computer_use/README.md +109 -0
  82. code_puppy_core_plugins/computer_use/__init__.py +1 -0
  83. code_puppy_core_plugins/computer_use/accessibility.py +163 -0
  84. code_puppy_core_plugins/computer_use/activation.py +75 -0
  85. code_puppy_core_plugins/computer_use/backend.py +584 -0
  86. code_puppy_core_plugins/computer_use/backend_types.py +5 -0
  87. code_puppy_core_plugins/computer_use/capture.py +110 -0
  88. code_puppy_core_plugins/computer_use/commands.py +62 -0
  89. code_puppy_core_plugins/computer_use/geometry.py +81 -0
  90. code_puppy_core_plugins/computer_use/inline_image.py +56 -0
  91. code_puppy_core_plugins/computer_use/keycodes.py +47 -0
  92. code_puppy_core_plugins/computer_use/policy.py +144 -0
  93. code_puppy_core_plugins/computer_use/register_callbacks.py +96 -0
  94. code_puppy_core_plugins/computer_use/safety.py +18 -0
  95. code_puppy_core_plugins/computer_use/settle.py +64 -0
  96. code_puppy_core_plugins/computer_use/state.py +86 -0
  97. code_puppy_core_plugins/computer_use/tools.py +469 -0
  98. code_puppy_core_plugins/context_indicator/__init__.py +14 -0
  99. code_puppy_core_plugins/context_indicator/register_callbacks.py +249 -0
  100. code_puppy_core_plugins/context_indicator/usage.py +40 -0
  101. code_puppy_core_plugins/copilot_auth/__init__.py +11 -0
  102. code_puppy_core_plugins/copilot_auth/config.py +93 -0
  103. code_puppy_core_plugins/copilot_auth/reasoning_client.py +409 -0
  104. code_puppy_core_plugins/copilot_auth/register_callbacks.py +460 -0
  105. code_puppy_core_plugins/copilot_auth/utils.py +587 -0
  106. code_puppy_core_plugins/customizable_commands/__init__.py +0 -0
  107. code_puppy_core_plugins/customizable_commands/register_callbacks.py +464 -0
  108. code_puppy_core_plugins/dbos_durable_exec/__init__.py +1 -0
  109. code_puppy_core_plugins/dbos_durable_exec/cancel.py +15 -0
  110. code_puppy_core_plugins/dbos_durable_exec/commands.py +31 -0
  111. code_puppy_core_plugins/dbos_durable_exec/config.py +31 -0
  112. code_puppy_core_plugins/dbos_durable_exec/lifecycle.py +83 -0
  113. code_puppy_core_plugins/dbos_durable_exec/register_callbacks.py +45 -0
  114. code_puppy_core_plugins/dbos_durable_exec/runtime.py +65 -0
  115. code_puppy_core_plugins/dbos_durable_exec/startup_lock.py +155 -0
  116. code_puppy_core_plugins/dbos_durable_exec/workflow_ids.py +16 -0
  117. code_puppy_core_plugins/dbos_durable_exec/wrapper.py +58 -0
  118. code_puppy_core_plugins/destructive_command_guard/AGENTS.md +79 -0
  119. code_puppy_core_plugins/destructive_command_guard/__init__.py +14 -0
  120. code_puppy_core_plugins/destructive_command_guard/detector.py +374 -0
  121. code_puppy_core_plugins/destructive_command_guard/register_callbacks.py +165 -0
  122. code_puppy_core_plugins/emoji_filter/__init__.py +12 -0
  123. code_puppy_core_plugins/emoji_filter/config.py +26 -0
  124. code_puppy_core_plugins/emoji_filter/register_callbacks.py +238 -0
  125. code_puppy_core_plugins/emoji_filter/stripper.py +45 -0
  126. code_puppy_core_plugins/empty_html_comment_filter/register_callbacks.py +116 -0
  127. code_puppy_core_plugins/example_custom_command/README.md +328 -0
  128. code_puppy_core_plugins/example_custom_command/register_callbacks.py +66 -0
  129. code_puppy_core_plugins/file_permission_handler/__init__.py +4 -0
  130. code_puppy_core_plugins/file_permission_handler/register_callbacks.py +575 -0
  131. code_puppy_core_plugins/flux_bootstrap/__init__.py +5 -0
  132. code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/_docs/README.md +173 -0
  133. code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/_docs/cheatsheet.md +86 -0
  134. code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/_docs/pipeline.md +167 -0
  135. code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/_docs/synopsis.md +392 -0
  136. code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/about.md +51 -0
  137. code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/address-feedback.md +129 -0
  138. code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/ask.md +211 -0
  139. code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/aug.md +181 -0
  140. code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/auto-pilot.md +71 -0
  141. code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/cheatsheet.md +16 -0
  142. code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/commit.md +103 -0
  143. code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/config.md +108 -0
  144. code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/create-pr.md +195 -0
  145. code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/exec.md +221 -0
  146. code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/new.md +151 -0
  147. code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/qa.md +208 -0
  148. code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/rebase.md +180 -0
  149. code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/review.md +304 -0
  150. code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/split.md +120 -0
  151. code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/squash-commits.md +179 -0
  152. code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/status.md +46 -0
  153. code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/tests.md +155 -0
  154. code_puppy_core_plugins/flux_bootstrap/bundled/scripts/flux_about.py +154 -0
  155. code_puppy_core_plugins/flux_bootstrap/bundled/scripts/flux_cheatsheet.py +248 -0
  156. code_puppy_core_plugins/flux_bootstrap/bundled/scripts/flux_status.py +345 -0
  157. code_puppy_core_plugins/flux_bootstrap/installer.py +256 -0
  158. code_puppy_core_plugins/flux_bootstrap/register_callbacks.py +71 -0
  159. code_puppy_core_plugins/force_push_guard/__init__.py +5 -0
  160. code_puppy_core_plugins/force_push_guard/detector.py +96 -0
  161. code_puppy_core_plugins/force_push_guard/register_callbacks.py +161 -0
  162. code_puppy_core_plugins/fork/__init__.py +7 -0
  163. code_puppy_core_plugins/fork/register_callbacks.py +445 -0
  164. code_puppy_core_plugins/frontend_emitter/__init__.py +25 -0
  165. code_puppy_core_plugins/frontend_emitter/emitter.py +249 -0
  166. code_puppy_core_plugins/frontend_emitter/register_callbacks.py +412 -0
  167. code_puppy_core_plugins/frontend_emitter/session_context.py +50 -0
  168. code_puppy_core_plugins/grok_oauth/__init__.py +6 -0
  169. code_puppy_core_plugins/grok_oauth/config.py +49 -0
  170. code_puppy_core_plugins/grok_oauth/oauth_flow.py +213 -0
  171. code_puppy_core_plugins/grok_oauth/register_callbacks.py +132 -0
  172. code_puppy_core_plugins/grok_oauth/utils.py +195 -0
  173. code_puppy_core_plugins/herdr/README.md +168 -0
  174. code_puppy_core_plugins/herdr/__init__.py +9 -0
  175. code_puppy_core_plugins/herdr/client.py +339 -0
  176. code_puppy_core_plugins/herdr/register_callbacks.py +140 -0
  177. code_puppy_core_plugins/herdr/reporter.py +212 -0
  178. code_puppy_core_plugins/herdr/smoke.py +143 -0
  179. code_puppy_core_plugins/herdr/sources.py +133 -0
  180. code_puppy_core_plugins/hook_creator/__init__.py +1 -0
  181. code_puppy_core_plugins/hook_creator/register_callbacks.py +33 -0
  182. code_puppy_core_plugins/hook_manager/__init__.py +1 -0
  183. code_puppy_core_plugins/hook_manager/config.py +290 -0
  184. code_puppy_core_plugins/hook_manager/hooks_menu.py +571 -0
  185. code_puppy_core_plugins/hook_manager/register_callbacks.py +227 -0
  186. code_puppy_core_plugins/meta_oauth/__init__.py +1 -0
  187. code_puppy_core_plugins/meta_oauth/config.py +55 -0
  188. code_puppy_core_plugins/meta_oauth/oauth_flow.py +109 -0
  189. code_puppy_core_plugins/meta_oauth/register_callbacks.py +154 -0
  190. code_puppy_core_plugins/meta_oauth/utils.py +252 -0
  191. code_puppy_core_plugins/namespace_skill_search/README.md +118 -0
  192. code_puppy_core_plugins/namespace_skill_search/__init__.py +15 -0
  193. code_puppy_core_plugins/namespace_skill_search/namespaces.py +125 -0
  194. code_puppy_core_plugins/namespace_skill_search/register_callbacks.py +99 -0
  195. code_puppy_core_plugins/namespace_skill_search/search_tool.py +158 -0
  196. code_puppy_core_plugins/no_tools/__init__.py +0 -0
  197. code_puppy_core_plugins/no_tools/register_callbacks.py +42 -0
  198. code_puppy_core_plugins/oauth_pasteback.py +110 -0
  199. code_puppy_core_plugins/oauth_puppy_html.py +194 -0
  200. code_puppy_core_plugins/obsidian_agent/README.md +52 -0
  201. code_puppy_core_plugins/obsidian_agent/__init__.py +8 -0
  202. code_puppy_core_plugins/obsidian_agent/agent_obsidian.py +147 -0
  203. code_puppy_core_plugins/obsidian_agent/register_callbacks.py +13 -0
  204. code_puppy_core_plugins/ollama/__init__.py +1 -0
  205. code_puppy_core_plugins/ollama/register_callbacks.py +127 -0
  206. code_puppy_core_plugins/ollama_setup/__init__.py +5 -0
  207. code_puppy_core_plugins/ollama_setup/completer.py +38 -0
  208. code_puppy_core_plugins/ollama_setup/register_callbacks.py +419 -0
  209. code_puppy_core_plugins/plugin_list/__init__.py +0 -0
  210. code_puppy_core_plugins/plugin_list/plugin_contributions.py +348 -0
  211. code_puppy_core_plugins/plugin_list/plugin_meta.py +67 -0
  212. code_puppy_core_plugins/plugin_list/plugin_text_utils.py +173 -0
  213. code_puppy_core_plugins/plugin_list/plugins_menu.py +455 -0
  214. code_puppy_core_plugins/plugin_list/plugins_menu_layout.py +194 -0
  215. code_puppy_core_plugins/plugin_list/plugins_menu_render.py +431 -0
  216. code_puppy_core_plugins/plugin_list/project_trust_flow.py +162 -0
  217. code_puppy_core_plugins/plugin_list/register_callbacks.py +281 -0
  218. code_puppy_core_plugins/pop_command/__init__.py +1 -0
  219. code_puppy_core_plugins/pop_command/register_callbacks.py +191 -0
  220. code_puppy_core_plugins/prompt_newline/__init__.py +13 -0
  221. code_puppy_core_plugins/prompt_newline/config.py +21 -0
  222. code_puppy_core_plugins/prompt_newline/register_callbacks.py +163 -0
  223. code_puppy_core_plugins/prune/__init__.py +1 -0
  224. code_puppy_core_plugins/prune/prune_menu.py +308 -0
  225. code_puppy_core_plugins/prune/prune_model.py +517 -0
  226. code_puppy_core_plugins/prune/prune_render.py +354 -0
  227. code_puppy_core_plugins/prune/register_callbacks.py +388 -0
  228. code_puppy_core_plugins/puppy_kennel/README.md +203 -0
  229. code_puppy_core_plugins/puppy_kennel/__init__.py +6 -0
  230. code_puppy_core_plugins/puppy_kennel/commands.py +206 -0
  231. code_puppy_core_plugins/puppy_kennel/config.py +36 -0
  232. code_puppy_core_plugins/puppy_kennel/kennel.py +368 -0
  233. code_puppy_core_plugins/puppy_kennel/packer.py +152 -0
  234. code_puppy_core_plugins/puppy_kennel/recorder.py +83 -0
  235. code_puppy_core_plugins/puppy_kennel/register_callbacks.py +109 -0
  236. code_puppy_core_plugins/puppy_kennel/retriever.py +28 -0
  237. code_puppy_core_plugins/puppy_kennel/schema.py +78 -0
  238. code_puppy_core_plugins/puppy_kennel/state.py +68 -0
  239. code_puppy_core_plugins/puppy_kennel/tools.py +449 -0
  240. code_puppy_core_plugins/puppy_kennel/wings.py +110 -0
  241. code_puppy_core_plugins/puppy_spinner/README.md +93 -0
  242. code_puppy_core_plugins/puppy_spinner/__init__.py +11 -0
  243. code_puppy_core_plugins/puppy_spinner/builtin_frames.py +172 -0
  244. code_puppy_core_plugins/puppy_spinner/commands.py +116 -0
  245. code_puppy_core_plugins/puppy_spinner/picker.py +379 -0
  246. code_puppy_core_plugins/puppy_spinner/register_callbacks.py +193 -0
  247. code_puppy_core_plugins/puppy_spinner/spinners.py +444 -0
  248. code_puppy_core_plugins/quick_resume/__init__.py +0 -0
  249. code_puppy_core_plugins/quick_resume/register_callbacks.py +77 -0
  250. code_puppy_core_plugins/review_pr/__init__.py +1 -0
  251. code_puppy_core_plugins/review_pr/register_callbacks.py +162 -0
  252. code_puppy_core_plugins/shell_safety/__init__.py +6 -0
  253. code_puppy_core_plugins/shell_safety/agent_shell_safety.py +69 -0
  254. code_puppy_core_plugins/shell_safety/command_cache.py +156 -0
  255. code_puppy_core_plugins/shell_safety/register_callbacks.py +203 -0
  256. code_puppy_core_plugins/stack_dump/__init__.py +1 -0
  257. code_puppy_core_plugins/stack_dump/register_callbacks.py +79 -0
  258. code_puppy_core_plugins/statusline/__init__.py +14 -0
  259. code_puppy_core_plugins/statusline/config.py +68 -0
  260. code_puppy_core_plugins/statusline/payload.py +138 -0
  261. code_puppy_core_plugins/statusline/prompt_patch.py +76 -0
  262. code_puppy_core_plugins/statusline/register_callbacks.py +45 -0
  263. code_puppy_core_plugins/statusline/runner.py +122 -0
  264. code_puppy_core_plugins/statusline/statusline_command.py +197 -0
  265. code_puppy_core_plugins/steer_queue/__init__.py +10 -0
  266. code_puppy_core_plugins/steer_queue/queue_menu.py +444 -0
  267. code_puppy_core_plugins/steer_queue/register_callbacks.py +138 -0
  268. code_puppy_core_plugins/subagent_panel/README.md +102 -0
  269. code_puppy_core_plugins/subagent_panel/__init__.py +24 -0
  270. code_puppy_core_plugins/subagent_panel/coalesce_patch.py +242 -0
  271. code_puppy_core_plugins/subagent_panel/panel_render.py +145 -0
  272. code_puppy_core_plugins/subagent_panel/register_callbacks.py +535 -0
  273. code_puppy_core_plugins/subagent_panel/resume_repaint.py +112 -0
  274. code_puppy_core_plugins/subagent_panel/state.py +231 -0
  275. code_puppy_core_plugins/switch_agent_resume/__init__.py +5 -0
  276. code_puppy_core_plugins/switch_agent_resume/register_callbacks.py +314 -0
  277. code_puppy_core_plugins/theme/README.md +86 -0
  278. code_puppy_core_plugins/theme/__init__.py +14 -0
  279. code_puppy_core_plugins/theme/bundled_palettes.py +346 -0
  280. code_puppy_core_plugins/theme/content_styles.py +146 -0
  281. code_puppy_core_plugins/theme/osc_palette.py +178 -0
  282. code_puppy_core_plugins/theme/picker.py +358 -0
  283. code_puppy_core_plugins/theme/prompt_toolkit_theme.py +113 -0
  284. code_puppy_core_plugins/theme/register_callbacks.py +348 -0
  285. code_puppy_core_plugins/theme/rich_themes.py +202 -0
  286. code_puppy_core_plugins/theme/themes.py +720 -0
  287. code_puppy_core_plugins/timestamp_heartbeat/__init__.py +1 -0
  288. code_puppy_core_plugins/timestamp_heartbeat/register_callbacks.py +114 -0
  289. code_puppy_core_plugins/token_ratio_learner/__init__.py +5 -0
  290. code_puppy_core_plugins/token_ratio_learner/ratios.py +208 -0
  291. code_puppy_core_plugins/token_ratio_learner/register_callbacks.py +213 -0
  292. code_puppy_core_plugins/universal_constructor/__init__.py +13 -0
  293. code_puppy_core_plugins/universal_constructor/models.py +138 -0
  294. code_puppy_core_plugins/universal_constructor/provider.py +62 -0
  295. code_puppy_core_plugins/universal_constructor/register_callbacks.py +75 -0
  296. code_puppy_core_plugins/universal_constructor/registry.py +302 -0
  297. code_puppy_core_plugins/universal_constructor/sandbox.py +584 -0
  298. code_puppy_core_plugins/wide_completion_menu/__init__.py +6 -0
  299. code_puppy_core_plugins/wide_completion_menu/register_callbacks.py +165 -0
  300. code_puppy_core_plugins/wiggum/__init__.py +1 -0
  301. code_puppy_core_plugins/wiggum/goal_runs.py +91 -0
  302. code_puppy_core_plugins/wiggum/judge.py +299 -0
  303. code_puppy_core_plugins/wiggum/judge_config.py +249 -0
  304. code_puppy_core_plugins/wiggum/judges_menu.py +814 -0
  305. code_puppy_core_plugins/wiggum/register_callbacks.py +569 -0
  306. code_puppy_core_plugins/wiggum/state.py +89 -0
  307. code_puppy_core_plugins/yolo_cli/__init__.py +1 -0
  308. code_puppy_core_plugins/yolo_cli/register_callbacks.py +41 -0
  309. code_puppy_core_plugins-0.0.2.dist-info/METADATA +64 -0
  310. code_puppy_core_plugins-0.0.2.dist-info/RECORD +313 -0
  311. code_puppy_core_plugins-0.0.2.dist-info/WHEEL +4 -0
  312. code_puppy_core_plugins-0.0.2.dist-info/entry_points.txt +55 -0
  313. code_puppy_core_plugins-0.0.2.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,494 @@
1
+ """``CodePuppyAgent`` — Code Puppy as a native Agent Client Protocol agent.
2
+
3
+ This implements the official SDK's ``Agent`` interface, so Code Puppy runs as
4
+ an external agent in any ACP client (Zed, and other editors that speak ACP).
5
+ The SDK owns the wire: ``acp.run_agent`` binds stdio, frames JSON-RPC, parses
6
+ params into typed models, and hands us a ``Client`` connection (via
7
+ ``on_connect``) for talking back to the client. We own the behaviour: mapping ACP sessions to Code Puppy agents,
8
+ running prompts, and translating events (through ``EventBridge``) and I/O
9
+ (through ``permissions`` + ``io_delegation``).
10
+
11
+ Only capability-gated methods we actually support are implemented; the SDK's
12
+ router resolves unimplemented ones to a clean "method not found", so we never
13
+ have to stub protocol surface we don't mean.
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ import asyncio
19
+ import logging
20
+ import uuid
21
+ from importlib.metadata import PackageNotFoundError, version
22
+ from typing import Any, Dict, List, Optional
23
+
24
+ from acp import Agent
25
+ from acp.schema import (
26
+ AgentCapabilities,
27
+ AuthenticateResponse,
28
+ AvailableCommand,
29
+ AvailableCommandsUpdate,
30
+ ClientCapabilities,
31
+ CloseSessionResponse,
32
+ Implementation,
33
+ InitializeResponse,
34
+ ListSessionsResponse,
35
+ LoadSessionResponse,
36
+ NewSessionResponse,
37
+ PromptResponse,
38
+ SessionInfo,
39
+ SetSessionModeResponse,
40
+ )
41
+
42
+ from code_puppy_core_plugins.acp import (
43
+ capabilities,
44
+ io_delegation,
45
+ mcp_config,
46
+ permissions,
47
+ persistence,
48
+ replay,
49
+ session_config,
50
+ state,
51
+ )
52
+ from code_puppy_core_plugins.acp.bridge import EventBridge
53
+ from code_puppy_core_plugins.acp.session import ACPSession
54
+
55
+ logger = logging.getLogger(__name__)
56
+
57
+ # ACP protocol version this plugin targets. Sourced from the SDK (not a literal) so a
58
+ # library upgrade can't silently advertise a stale version; falls back to v1 if absent.
59
+ try:
60
+ from acp import PROTOCOL_VERSION as PROTOCOL_VERSION
61
+ except ImportError: # pragma: no cover - defensive for older SDKs
62
+ PROTOCOL_VERSION = 1
63
+
64
+
65
+ def _code_puppy_version() -> str:
66
+ try:
67
+ return version("code-puppy")
68
+ except PackageNotFoundError:
69
+ return "0.0.0"
70
+
71
+
72
+ class CodePuppyAgent(Agent):
73
+ """One ACP connection's worth of Code Puppy, spread across client threads."""
74
+
75
+ def __init__(self) -> None:
76
+ self._sessions: Dict[str, ACPSession] = {}
77
+ self._bridge = EventBridge()
78
+ self._client_caps: Optional[ClientCapabilities] = None
79
+
80
+ # ---- Connection lifecycle ---------------------------------------------
81
+ def on_connect(self, conn: Any) -> None:
82
+ """Store the client handle + loop, wire events, install approvals.
83
+
84
+ Called synchronously by the SDK from inside ``run_agent`` — already on
85
+ the running event loop — so ``get_running_loop`` returns the loop our
86
+ permission and I/O bridges marshal onto.
87
+ """
88
+ state.set_connection(conn, asyncio.get_running_loop())
89
+ self._bridge.register()
90
+ permissions.install()
91
+
92
+ def shutdown(self) -> None:
93
+ """Unwire this agent's event hooks. Call once the connection ends.
94
+
95
+ ``permissions`` and ``io_delegation`` are torn down by the plugin entry
96
+ point; this drops the ``EventBridge`` hooks it owns so a closed
97
+ connection leaves the global callback registry clean.
98
+ """
99
+ self._bridge.unregister()
100
+
101
+ # ---- Handshake --------------------------------------------------------
102
+ async def initialize(
103
+ self,
104
+ protocol_version: int,
105
+ client_capabilities: Optional[ClientCapabilities] = None,
106
+ client_info: Optional[Implementation] = None,
107
+ **kwargs: Any,
108
+ ) -> InitializeResponse:
109
+ """Negotiate capabilities and install matching I/O delegation.
110
+
111
+ Once we know what the client can do, reroute Code Puppy's workspace
112
+ file I/O and shell to the client's ``fs/*`` / ``terminal/*`` methods
113
+ (only the edges
114
+ the client advertises). Everything else stays local.
115
+ """
116
+ self._client_caps = client_capabilities
117
+ io_delegation.install(client_capabilities)
118
+ return InitializeResponse(
119
+ protocol_version=PROTOCOL_VERSION,
120
+ agent_capabilities=self._agent_capabilities(),
121
+ agent_info=Implementation(
122
+ name="code-puppy",
123
+ title="Code Puppy",
124
+ version=_code_puppy_version(),
125
+ ),
126
+ )
127
+
128
+ async def authenticate(self, method_id: str, **kwargs: Any) -> AuthenticateResponse:
129
+ """No auth flow — Code Puppy authenticates via its own model config."""
130
+ return AuthenticateResponse()
131
+
132
+ # ---- Session lifecycle ------------------------------------------------
133
+ async def new_session(
134
+ self,
135
+ cwd: str,
136
+ additional_directories: Optional[List[str]] = None,
137
+ mcp_servers: Optional[List[Any]] = None,
138
+ **kwargs: Any,
139
+ ) -> NewSessionResponse:
140
+ """Create a session bound to a fresh agent instance.
141
+
142
+ Uses ``load_agent`` (not the cached ``get_current_agent``) so each
143
+ client thread gets its own ``_message_history``. ``cwd`` +
144
+ ``additional_directories`` anchor the session's tools; ``mcp_servers``
145
+ the client injects are attached to the agent.
146
+ """
147
+ session_id = f"sess_{uuid.uuid4().hex[:16]}"
148
+ self._make_session(session_id, cwd, additional_directories, mcp_servers)
149
+ self._announce_commands_soon(session_id)
150
+ return NewSessionResponse(
151
+ session_id=session_id,
152
+ config_options=session_config.config_options() or None,
153
+ )
154
+
155
+ async def load_session(
156
+ self,
157
+ cwd: str,
158
+ session_id: str,
159
+ additional_directories: Optional[List[str]] = None,
160
+ mcp_servers: Optional[List[Any]] = None,
161
+ **kwargs: Any,
162
+ ) -> LoadSessionResponse:
163
+ """Re-open a thread the client remembers, replaying persisted history.
164
+
165
+ If we have the session's history on disk (persisted after each turn),
166
+ it is rehydrated into the fresh agent so the model continues the real
167
+ conversation, AND replayed to the client as ``session/update``
168
+ notifications so the client rebuilds the thread UI (without this the
169
+ client shows -- and may discard -- an empty thread). Otherwise the
170
+ thread is re-created empty but functional.
171
+ """
172
+ session = self._make_session(
173
+ session_id, cwd, additional_directories, mcp_servers, rehydrate=True
174
+ )
175
+ await replay.replay_history(session_id, session.agent.get_message_history())
176
+ self._announce_commands_soon(session_id)
177
+ return LoadSessionResponse(
178
+ config_options=session_config.config_options() or None,
179
+ )
180
+
181
+ async def resume_session(
182
+ self,
183
+ cwd: str,
184
+ session_id: str,
185
+ additional_directories: Optional[List[str]] = None,
186
+ mcp_servers: Optional[List[Any]] = None,
187
+ **kwargs: Any,
188
+ ) -> Any:
189
+ """Resume a session across a restart, rehydrating + replaying history."""
190
+ from acp.schema import ResumeSessionResponse
191
+
192
+ session = self._make_session(
193
+ session_id, cwd, additional_directories, mcp_servers, rehydrate=True
194
+ )
195
+ await replay.replay_history(session_id, session.agent.get_message_history())
196
+ self._announce_commands_soon(session_id)
197
+ return ResumeSessionResponse(
198
+ config_options=session_config.config_options() or None,
199
+ )
200
+
201
+ async def fork_session(
202
+ self,
203
+ cwd: str,
204
+ session_id: str,
205
+ additional_directories: Optional[List[str]] = None,
206
+ mcp_servers: Optional[List[Any]] = None,
207
+ **kwargs: Any,
208
+ ) -> Any:
209
+ """Branch a session: duplicate its history into a new session id.
210
+
211
+ The source's history is copied into a fresh agent so the fork continues
212
+ the conversation independently. The source may be a live in-memory
213
+ session OR one persisted by a prior process -- forking must survive a
214
+ restart just like ``load``/``resume`` do, so we fall back to the
215
+ pickled history when the source isn't live.
216
+ """
217
+ from acp.schema import ForkSessionResponse
218
+
219
+ source = self._sessions.get(session_id)
220
+ if source is not None:
221
+ source_history = list(source.agent.get_message_history())
222
+ source_cwd = source.cwd
223
+ else:
224
+ source_history = persistence.load_history(session_id)
225
+ if source_history is None:
226
+ raise ValueError(f"unknown session to fork: {session_id}")
227
+ source_cwd = None
228
+ new_id = f"sess_{uuid.uuid4().hex[:16]}"
229
+ session = self._make_session(
230
+ new_id,
231
+ cwd or source_cwd or "",
232
+ additional_directories,
233
+ mcp_servers,
234
+ )
235
+ try:
236
+ session.agent.set_message_history(source_history)
237
+ except Exception: # noqa: BLE001
238
+ logger.debug("ACP: fork history copy failed", exc_info=True)
239
+ self._announce_commands_soon(new_id)
240
+ return ForkSessionResponse(
241
+ session_id=new_id,
242
+ config_options=session_config.config_options() or None,
243
+ )
244
+
245
+ async def set_session_mode(
246
+ self, mode_id: str, session_id: str, **kwargs: Any
247
+ ) -> SetSessionModeResponse:
248
+ """No-op mode handler.
249
+
250
+ Code Puppy has no ACP *session modes* (e.g. plan vs default); model
251
+ selection is exposed as a ``model`` config option instead (that is what
252
+ clients bind their model picker to -- see ``session_config``). This
253
+ method exists only to satisfy the SDK router's ``session/set_mode``
254
+ route; any mode id is accepted as a no-op.
255
+ """
256
+ return SetSessionModeResponse()
257
+
258
+ def _rebind_session_model(self, session_id: str) -> None:
259
+ """Rebuild a live session's agent on the current model, keeping state.
260
+
261
+ Message history and any client-injected MCP servers are preserved, so
262
+ the switch is invisible to the conversation. Best-effort: a rebind
263
+ failure leaves the existing agent in place.
264
+ """
265
+ session = self._sessions.get(session_id)
266
+ if session is None:
267
+ return
268
+ try:
269
+ history = list(session.agent.get_message_history())
270
+ session.agent = self._new_agent()
271
+ session.agent.set_message_history(history)
272
+ if session.mcp_specs:
273
+ mcp_config.attach(session.agent, session.mcp_specs)
274
+ except Exception: # noqa: BLE001
275
+ logger.debug("ACP: model rebind failed", exc_info=True)
276
+
277
+ async def set_config_option(
278
+ self, config_id: str, session_id: str, value: Any, **kwargs: Any
279
+ ) -> Any:
280
+ """Apply a config-option change and return the refreshed options.
281
+
282
+ A change to the ``model`` option rebinds the live session's agent to the
283
+ newly-selected model (history + client MCP servers preserved), so the
284
+ client's model picker switches the model mid-thread.
285
+ """
286
+ from acp.schema import SetSessionConfigOptionResponse
287
+
288
+ options = session_config.apply_config_option(config_id, value)
289
+ if config_id == session_config.MODEL_OPTION_ID:
290
+ self._rebind_session_model(session_id)
291
+ return SetSessionConfigOptionResponse(config_options=options or None)
292
+
293
+ async def list_sessions(
294
+ self, cursor: Optional[str] = None, cwd: Optional[str] = None, **kwargs: Any
295
+ ) -> ListSessionsResponse:
296
+ """List every revivable session: live in-memory + persisted on disk.
297
+
298
+ Live sessions (this process) merge with sessions persisted to disk in
299
+ prior runs, so a client's picker still shows -- and can
300
+ ``session/load`` / ``session/resume`` -- threads that outlived the
301
+ process that made them. Live wins on id collision (it carries the
302
+ freshest state). Uncursored single page; optional ``cwd`` filter.
303
+ """
304
+ infos: List[SessionInfo] = []
305
+ seen: set[str] = set()
306
+ for s in self._sessions.values():
307
+ if cwd is not None and s.cwd != cwd:
308
+ continue
309
+ seen.add(s.session_id)
310
+ infos.append(
311
+ SessionInfo(
312
+ session_id=s.session_id,
313
+ cwd=s.cwd or cwd or "",
314
+ additional_directories=s.additional_directories or None,
315
+ )
316
+ )
317
+ for record in persistence.list_persisted():
318
+ if record.session_id in seen:
319
+ continue
320
+ if cwd is not None and record.cwd != cwd:
321
+ continue
322
+ seen.add(record.session_id)
323
+ infos.append(
324
+ SessionInfo(
325
+ session_id=record.session_id,
326
+ cwd=record.cwd or cwd or "",
327
+ additional_directories=record.additional_directories or None,
328
+ )
329
+ )
330
+ return ListSessionsResponse(sessions=infos, next_cursor=None)
331
+
332
+ async def close_session(
333
+ self, session_id: str, **kwargs: Any
334
+ ) -> CloseSessionResponse:
335
+ """Drop a session, cancelling any in-flight run first.
336
+
337
+ A close is a deliberate act, so its persisted history is deleted too --
338
+ otherwise the session would resurrect in the next ``list_sessions``,
339
+ which is exactly the "disappeared session that won't stay gone" bug in
340
+ reverse.
341
+
342
+ Also purges this session's own bucket of
343
+ ``load_model_with_fallback``'s once-per-conversation dead-model-warning
344
+ dedup (keyed by the session's conversation root id -- see
345
+ ``subagent_invocation.py`` / ``subagent_context.py``). Sub-agent
346
+ warnings are scoped per session precisely so they never leak into any
347
+ OTHER session; without this, a long-running server churning through
348
+ many short-lived sessions would accumulate one dangling bucket per
349
+ closed session forever.
350
+
351
+ Waits for any in-flight run to actually finish unwinding
352
+ (``cancel_and_wait``, not the bare ``cancel``) before purging --
353
+ otherwise a run still mid-flight inside ``_invoke_agent_impl`` could
354
+ write a fresh warning into this session's bucket a moment *after*
355
+ the purge, leaking that one entry forever (nothing will call
356
+ ``close_session`` for this id a second time).
357
+ """
358
+ from code_puppy.agents._builder import reset_model_fallback_warnings
359
+
360
+ session = self._sessions.pop(session_id, None)
361
+ if session is not None:
362
+ await session.cancel_and_wait()
363
+ persistence.delete(session_id)
364
+ reset_model_fallback_warnings(scope=session_id)
365
+ return CloseSessionResponse()
366
+
367
+ # ---- Prompt turn ------------------------------------------------------
368
+ async def prompt(
369
+ self, prompt: List[Any], session_id: str, **kwargs: Any
370
+ ) -> PromptResponse:
371
+ """Run the agent on a user prompt, streaming updates via the bridge."""
372
+ session = self._sessions.get(session_id)
373
+ if session is None:
374
+ raise ValueError(f"unknown session: {session_id}")
375
+ outcome = await session.prompt(prompt)
376
+ return PromptResponse(stop_reason=outcome.stop_reason, usage=outcome.usage)
377
+
378
+ async def cancel(self, session_id: str, **kwargs: Any) -> None:
379
+ """Cancel the in-flight run for a session (notification)."""
380
+ session = self._sessions.get(session_id)
381
+ if session is not None:
382
+ session.cancel()
383
+
384
+ # ---- Helpers ----------------------------------------------------------
385
+ def _agent_capabilities(self) -> AgentCapabilities:
386
+ return capabilities.agent_capabilities()
387
+
388
+ def _make_session(
389
+ self,
390
+ session_id: str,
391
+ cwd: str,
392
+ additional_directories: Optional[List[str]],
393
+ mcp_servers: Optional[List[Any]],
394
+ *,
395
+ rehydrate: bool = False,
396
+ ) -> ACPSession:
397
+ """Build + register an ``ACPSession`` with a fresh agent.
398
+
399
+ When ``rehydrate`` is set, any persisted history for ``session_id`` is
400
+ replayed into the agent so the model continues the real conversation.
401
+ Client-injected ``mcp_servers`` are attached best-effort.
402
+
403
+ Also resets the SHARED/unscoped bucket of
404
+ ``load_model_with_fallback``'s once-per-conversation
405
+ pinned-model-unavailable dedup (see ``_builder.reset_model_fallback_warnings``).
406
+ Sub-agent invocations scope their own warning state to the
407
+ conversation's ROOT id (a ContextVar -- see
408
+ ``subagent_context.get_conversation_root_id``/``session.py``'s prompt
409
+ handler), so they already can't leak across sessions and don't need
410
+ this reset at all. The *main* agent build path
411
+ (``build_pydantic_agent``, used to build each session's own
412
+ top-level agent) still shares one unscoped bucket across every
413
+ session in this process, matching the pre-existing
414
+ single-main-agent-per-process model -- so without this reset, session
415
+ A hitting a dead pin during its own build could silently suppress the
416
+ identical warning for session B's build too. Resetting only the
417
+ ``scope=None`` bucket on every new/loaded/forked session avoids that
418
+ without touching any other session's already-scoped sub-agent
419
+ warnings.
420
+ """
421
+ from code_puppy.agents._builder import reset_model_fallback_warnings
422
+
423
+ reset_model_fallback_warnings(scope=None)
424
+ agent = self._new_agent()
425
+ if rehydrate:
426
+ history = persistence.load_history(session_id)
427
+ if history:
428
+ try:
429
+ agent.set_message_history(history)
430
+ except Exception: # noqa: BLE001
431
+ logger.debug("ACP: history rehydrate failed", exc_info=True)
432
+ if mcp_servers:
433
+ mcp_config.attach(agent, mcp_servers)
434
+ session = ACPSession(
435
+ session_id,
436
+ agent,
437
+ cwd=cwd,
438
+ additional_directories=additional_directories,
439
+ mcp_specs=mcp_servers,
440
+ )
441
+ self._sessions[session_id] = session
442
+ return session
443
+
444
+ @staticmethod
445
+ def _new_agent() -> Any:
446
+ from code_puppy.agents.agent_manager import get_current_agent_name, load_agent
447
+
448
+ return load_agent(get_current_agent_name())
449
+
450
+ def _announce_commands_soon(self, session_id: str) -> None:
451
+ """Schedule an ``available_commands_update`` after the response ships.
452
+
453
+ We must not send the update before the ``new_session``/``load_session``
454
+ reply reaches the client (it wouldn't know the session yet).
455
+ Scheduling a
456
+ task defers it until this coroutine yields, i.e. after the reply.
457
+ """
458
+ loop = state.get_loop()
459
+ if loop is not None:
460
+ loop.create_task(self._announce_commands(session_id))
461
+
462
+ async def _announce_commands(self, session_id: str) -> None:
463
+ """Tell the client which slash commands Code Puppy exposes.
464
+
465
+ Deferred behind a short delay: ``create_task`` only yields one tick,
466
+ which isn't enough to guarantee the ``new_session`` reply has been
467
+ serialized onto the wire. Without this the client can receive the
468
+ notification before it knows the session id and drop it as "unknown
469
+ session". 100ms is imperceptible and comfortably after the reply.
470
+ """
471
+ await asyncio.sleep(0.1)
472
+ connection = state.get_connection()
473
+ if connection is None:
474
+ return
475
+ try:
476
+ from code_puppy.command_line.command_registry import get_unique_commands
477
+
478
+ available = [
479
+ AvailableCommand(name=c.name, description=c.description)
480
+ for c in get_unique_commands()
481
+ ]
482
+ except Exception: # noqa: BLE001
483
+ logger.debug("ACP: could not enumerate slash commands", exc_info=True)
484
+ return
485
+ if not available:
486
+ return
487
+ update = AvailableCommandsUpdate(
488
+ session_update="available_commands_update",
489
+ available_commands=available,
490
+ )
491
+ try:
492
+ await connection.session_update(session_id, update)
493
+ except Exception: # noqa: BLE001
494
+ logger.debug("ACP: available_commands_update failed", exc_info=True)