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,517 @@
1
+ """Data model and pydantic-ai introspection for /prune.
2
+
3
+ Kept separate from prune_menu.py so the TUI file stays focused on
4
+ prompt_toolkit wiring. Everything here is pure data-shape + parsing.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from dataclasses import dataclass, field
10
+ from typing import Any, List, Optional, Set
11
+
12
+ # ── tool-name → side-effect classification ─────────────────────────────────
13
+
14
+ _WRITE_TOOLS = {
15
+ "edit_file",
16
+ "create_file",
17
+ "replace_in_file",
18
+ "delete_snippet",
19
+ "delete_file",
20
+ }
21
+ _SHELL_TOOLS = {"agent_run_shell_command"}
22
+ _BROWSER_PREFIX = "browser_"
23
+ _TERMINAL_PREFIX = "terminal_"
24
+
25
+ SIDE_EFFECT_ICONS = {"⚡", "✎", "🌐", "▶"}
26
+
27
+
28
+ def classify_tool(tool_name: str) -> str:
29
+ """Return a short single-char icon hinting at the side-effect kind."""
30
+ if tool_name in _WRITE_TOOLS:
31
+ return "✎"
32
+ if tool_name in _SHELL_TOOLS:
33
+ return "⚡"
34
+ if tool_name.startswith(_BROWSER_PREFIX):
35
+ return "🌐"
36
+ if tool_name.startswith(_TERMINAL_PREFIX):
37
+ return "▶"
38
+ return "·"
39
+
40
+
41
+ # ── data classes ───────────────────────────────────────────────────────────
42
+
43
+
44
+ @dataclass
45
+ class ToolCallInfo:
46
+ """One tool call within a message."""
47
+
48
+ tool_call_id: str
49
+ name: str
50
+ args_preview: str # short single-line summary, for the list pane
51
+ full_args: dict = field(default_factory=dict) # full args, for detail pane
52
+ icon: str = "·"
53
+ has_return: bool = False
54
+
55
+
56
+ @dataclass
57
+ class MessageEntry:
58
+ """One displayable message in the prune menu."""
59
+
60
+ history_index: int
61
+ role: str # "system" | "user" | "assistant" | "tool-return" | "unknown"
62
+ preview: str
63
+ full_text: str
64
+ tool_calls: List[ToolCallInfo] = field(default_factory=list)
65
+ tool_return_ids: List[str] = field(default_factory=list)
66
+ # Keep ThinkingPart content separate so previews show the user-facing answer
67
+ # while detail panes can still expose the model's reasoning.
68
+ thinking_segments: List[str] = field(default_factory=list)
69
+ # Context-window annotations; None when no estimator is available.
70
+ tokens: Optional[int] = None
71
+ in_context: Optional[bool] = None
72
+
73
+ @property
74
+ def is_pure_tool_return(self) -> bool:
75
+ """True for messages whose only content is tool returns.
76
+
77
+ These tag along with their parent tool-calling message and are
78
+ never shown as standalone rows in the menu.
79
+ """
80
+ return self.role == "tool-return"
81
+
82
+ @property
83
+ def is_locked(self) -> bool:
84
+ """True when this entry carries a ``SystemPromptPart`` and so
85
+ must never be pruned.
86
+
87
+ ``build_message_entries`` tags any request containing a
88
+ ``SystemPromptPart`` with ``role == "system"``, which covers
89
+ both a standalone system message and pydantic-ai's bundled
90
+ ``SystemPromptPart + UserPromptPart`` request.
91
+ """
92
+ return self.role == "system"
93
+
94
+ @property
95
+ def role_color(self) -> str:
96
+ if self.role == "system":
97
+ return "class:tui.title"
98
+ if self.role == "user":
99
+ return "class:tui.success"
100
+ if self.role == "assistant":
101
+ return "class:tui.header"
102
+ if self.role == "tool-return":
103
+ return "class:tui.warning"
104
+ return "class:tui.muted"
105
+
106
+
107
+ @dataclass
108
+ class Row:
109
+ """One visible row in the TUI list — always a whole-message header.
110
+
111
+ Thin named wrapper around ``message_idx`` so call sites read as
112
+ ``row.message_idx`` rather than a bare int that needs context. The
113
+ menu operates on whole entries only; individual tool calls within a
114
+ message are not separately selectable.
115
+ """
116
+
117
+ message_idx: int # index into MessageEntry list (not history_index)
118
+
119
+
120
+ @dataclass
121
+ class PruneSelection:
122
+ """Result of the menu — what the caller should remove.
123
+
124
+ Only whole messages can be selected. Their tool calls (and the
125
+ matching tool returns elsewhere in history) come along for the ride
126
+ via cascade logic in ``_perform_prune``.
127
+ """
128
+
129
+ history_indices_to_drop: Set[int] = field(default_factory=set)
130
+
131
+ @property
132
+ def is_empty(self) -> bool:
133
+ return not self.history_indices_to_drop
134
+
135
+
136
+ @dataclass
137
+ class ContextBudget:
138
+ """Snapshot of context-window math at menu open time.
139
+
140
+ ``used_tokens`` represents what would actually be sent on the next
141
+ turn — i.e. the sum of in-context message tokens, NOT every message
142
+ in history. Messages older than the truncation point are silently
143
+ dropped by the model and accounted for separately in
144
+ ``out_of_context_tokens`` so the budget percentage never exceeds 100%.
145
+
146
+ All fields default to None when the agent or its estimator is
147
+ unavailable — the menu degrades gracefully when this happens.
148
+ """
149
+
150
+ used_tokens: Optional[int] = None # in-context message tokens (what fits)
151
+ overhead_tokens: Optional[int] = None # system prompt + tool defs
152
+ context_length: Optional[int] = None # model's max context size
153
+ out_of_context_tokens: int = 0 # tokens from messages that won't be sent
154
+ out_of_context_messages: int = 0 # count of those messages
155
+ available: bool = False # True if the rest of the fields are meaningful
156
+
157
+ @property
158
+ def total_used(self) -> Optional[int]:
159
+ if self.used_tokens is None or self.overhead_tokens is None:
160
+ return None
161
+ return self.used_tokens + self.overhead_tokens
162
+
163
+ @property
164
+ def percent_used(self) -> Optional[float]:
165
+ if not self.available or not self.context_length:
166
+ return None
167
+ total = self.total_used or 0
168
+ return 100.0 * total / self.context_length
169
+
170
+
171
+ # ── string helpers ─────────────────────────────────────────────────────────
172
+
173
+
174
+ def short_str(value: Any, limit: int = 80) -> str:
175
+ if value is None:
176
+ return ""
177
+ s = str(value).replace("\n", " ").replace("\r", " ").strip()
178
+ if len(s) > limit:
179
+ return s[: limit - 1] + "…"
180
+ return s
181
+
182
+
183
+ def short_args(args: dict, limit: int = 80) -> str:
184
+ if not args:
185
+ return ""
186
+ items: List[str] = []
187
+ for k, v in list(args.items())[:4]:
188
+ vs = short_str(v, limit=20)
189
+ items.append(f"{k}={vs}")
190
+ joined = ", ".join(items)
191
+ if len(joined) > limit:
192
+ return joined[: limit - 1] + "…"
193
+ return joined
194
+
195
+
196
+ # ── pydantic-ai introspection ──────────────────────────────────────────────
197
+
198
+
199
+ def _extract_message(message: Any) -> Optional[MessageEntry]:
200
+ """Inspect a pydantic-ai message and produce a MessageEntry, or None
201
+ if it's the system prompt / something we shouldn't show."""
202
+ try:
203
+ from pydantic_ai.messages import (
204
+ ModelRequest,
205
+ ModelResponse,
206
+ SystemPromptPart,
207
+ TextPart,
208
+ ToolCallPart,
209
+ ToolReturnPart,
210
+ UserPromptPart,
211
+ )
212
+
213
+ try:
214
+ from pydantic_ai.messages import ThinkingPart # type: ignore
215
+ except Exception: # pragma: no cover — older pydantic-ai
216
+ ThinkingPart = None # type: ignore[assignment]
217
+
218
+ try:
219
+ from pydantic_ai.messages import RetryPromptPart # type: ignore
220
+ except Exception: # pragma: no cover — older pydantic-ai
221
+ RetryPromptPart = None # type: ignore[assignment]
222
+ except Exception:
223
+ return MessageEntry(
224
+ history_index=-1,
225
+ role="unknown",
226
+ preview=short_str(message),
227
+ full_text=str(message),
228
+ )
229
+
230
+ if isinstance(message, ModelRequest):
231
+ parts = getattr(message, "parts", []) or []
232
+ text_fragments: List[str] = []
233
+ user_text_fragments: List[str] = []
234
+ saw_user = False
235
+ saw_tool_return = False
236
+ saw_system = False
237
+ tool_return_ids: List[str] = []
238
+
239
+ for part in parts:
240
+ if isinstance(part, SystemPromptPart):
241
+ saw_system = True
242
+ text_fragments.append(f"[system] {part.content}")
243
+ elif isinstance(part, UserPromptPart):
244
+ saw_user = True
245
+ content = part.content
246
+ if isinstance(content, list):
247
+ user_text = (
248
+ " ".join(str(item) for item in content if isinstance(item, str))
249
+ or "<non-text content>"
250
+ )
251
+ else:
252
+ user_text = str(content)
253
+ user_text_fragments.append(user_text)
254
+ text_fragments.append(user_text)
255
+ elif isinstance(part, ToolReturnPart):
256
+ saw_tool_return = True
257
+ tcid = getattr(part, "tool_call_id", None)
258
+ if tcid:
259
+ tool_return_ids.append(tcid)
260
+ # Keep the FULL content here so the detail pane can show
261
+ # everything. The list pane builds its own short preview.
262
+ content_str = str(part.content) if part.content is not None else ""
263
+ text_fragments.append(f"[tool-return: {part.tool_name}] {content_str}")
264
+ elif RetryPromptPart is not None and isinstance(part, RetryPromptPart):
265
+ # RetryPromptPart reports tool-argument validation failures; treat it
266
+ # like ToolReturnPart so the parent call pairs and the retry is visible.
267
+ saw_tool_return = True
268
+ tcid = getattr(part, "tool_call_id", None)
269
+ if tcid:
270
+ tool_return_ids.append(tcid)
271
+ content_str = str(part.content) if part.content is not None else ""
272
+ tool_name = getattr(part, "tool_name", "?")
273
+ text_fragments.append(f"[retry-prompt: {tool_name}] {content_str}")
274
+
275
+ if saw_system and not (saw_user or saw_tool_return):
276
+ return None # system-only prompt — never show, never prunable
277
+
278
+ # System > user > tool-return: bundled system+user requests stay locked
279
+ # because the system prompt is always in context.
280
+ if saw_system:
281
+ role = "system"
282
+ elif saw_user:
283
+ role = "user"
284
+ elif saw_tool_return:
285
+ role = "tool-return"
286
+ else:
287
+ role = "unknown"
288
+
289
+ text = "\n".join(text_fragments).strip() or "<empty request>"
290
+ # For system+user bundles, preview user text—the useful part when scanning
291
+ # old turns.
292
+ if saw_system and user_text_fragments:
293
+ preview_source = "\n".join(user_text_fragments)
294
+ else:
295
+ preview_source = text
296
+ return MessageEntry(
297
+ history_index=-1,
298
+ role=role,
299
+ preview=short_str(preview_source, limit=80),
300
+ full_text=text,
301
+ tool_calls=[],
302
+ tool_return_ids=tool_return_ids,
303
+ )
304
+
305
+ if isinstance(message, ModelResponse):
306
+ parts = getattr(message, "parts", []) or []
307
+ text_fragments: List[str] = []
308
+ thinking_segments: List[str] = []
309
+ tool_calls: List[ToolCallInfo] = []
310
+ for part in parts:
311
+ if isinstance(part, TextPart):
312
+ text_fragments.append(str(part.content))
313
+ elif ThinkingPart is not None and isinstance(part, ThinkingPart):
314
+ # Keep thinking content out of the preview line — it would
315
+ # bury the user-facing answer in chain-of-thought noise.
316
+ content = getattr(part, "content", None)
317
+ if content:
318
+ thinking_segments.append(str(content))
319
+ elif isinstance(part, ToolCallPart):
320
+ try:
321
+ args_dict = part.args_as_dict()
322
+ except Exception:
323
+ args_dict = {}
324
+ tool_calls.append(
325
+ ToolCallInfo(
326
+ tool_call_id=getattr(part, "tool_call_id", "") or "",
327
+ name=part.tool_name,
328
+ args_preview=short_args(args_dict),
329
+ full_args=args_dict if isinstance(args_dict, dict) else {},
330
+ icon=classify_tool(part.tool_name),
331
+ )
332
+ )
333
+
334
+ text = "\n".join(text_fragments).strip()
335
+ if not text and tool_calls:
336
+ text = f"<{len(tool_calls)} tool call(s)>"
337
+ elif not text:
338
+ text = "<empty response>"
339
+
340
+ # Compose the detail-pane body: response text first (what humans
341
+ # care about), thinking content below in a clearly fenced section.
342
+ if thinking_segments:
343
+ thinking_block = "\n".join(thinking_segments).strip()
344
+ full_text = f"{text}\n\n[thinking]\n{thinking_block}"
345
+ else:
346
+ full_text = text
347
+
348
+ return MessageEntry(
349
+ history_index=-1,
350
+ role="assistant",
351
+ preview=short_str(text, limit=80),
352
+ full_text=full_text,
353
+ tool_calls=tool_calls,
354
+ thinking_segments=thinking_segments,
355
+ )
356
+
357
+ return MessageEntry(
358
+ history_index=-1,
359
+ role="unknown",
360
+ preview=short_str(message),
361
+ full_text=str(message),
362
+ )
363
+
364
+
365
+ def build_message_entries(raw_history: List[Any]) -> List[MessageEntry]:
366
+ """Turn pydantic-ai history into a list of MessageEntry, preserving order.
367
+
368
+ Pure-system messages in raw history are filtered out. Tool-return-only
369
+ messages stay in the list but are flagged so the menu can hide them
370
+ from the top level and surface them via the parent tool calls instead.
371
+
372
+ The sys row (when shown) comes exclusively from real history (e.g. a
373
+ ``SystemPromptPart`` bundled in ``history[0]``); no synthetic sys row
374
+ is ever injected. This avoids duplicate-at-index-1 issues with
375
+ transports that fold the system prompt into the first user message
376
+ (e.g. claude-code OAuth).
377
+ """
378
+ return_ids: Set[str] = set()
379
+ try:
380
+ from pydantic_ai.messages import ModelRequest, ToolReturnPart
381
+
382
+ try:
383
+ from pydantic_ai.messages import RetryPromptPart # type: ignore
384
+ except Exception: # pragma: no cover — older pydantic-ai
385
+ RetryPromptPart = None # type: ignore[assignment]
386
+
387
+ # ToolReturnPart and RetryPromptPart both satisfy a parent ToolCallPart.
388
+ tool_reply_kinds: tuple = (ToolReturnPart,)
389
+ if RetryPromptPart is not None:
390
+ tool_reply_kinds = (ToolReturnPart, RetryPromptPart)
391
+
392
+ for msg in raw_history:
393
+ if isinstance(msg, ModelRequest):
394
+ for part in getattr(msg, "parts", []) or []:
395
+ if isinstance(part, tool_reply_kinds):
396
+ tcid = getattr(part, "tool_call_id", None)
397
+ if tcid:
398
+ return_ids.add(tcid)
399
+ except Exception:
400
+ pass
401
+
402
+ entries: List[MessageEntry] = []
403
+ for hist_idx, msg in enumerate(raw_history):
404
+ entry = _extract_message(msg)
405
+ if entry is None:
406
+ continue
407
+ entry.history_index = hist_idx
408
+ for tc in entry.tool_calls:
409
+ tc.has_return = tc.tool_call_id in return_ids
410
+ entries.append(entry)
411
+
412
+ return entries
413
+
414
+
415
+ def annotate_context_window(
416
+ entries: List[MessageEntry],
417
+ raw_history: List[Any],
418
+ agent: Any,
419
+ ) -> ContextBudget:
420
+ """Mutate `entries` to set tokens + in_context, and return the budget.
421
+
422
+ Walks the entries newest → oldest, accumulating per-message token
423
+ estimates against ``context_length - overhead``. Each entry that fits
424
+ inside the remaining budget is marked in_context=True; once we blow
425
+ past the budget every older entry gets in_context=False.
426
+
427
+ Fails open: if the agent doesn't expose the expected helpers, all
428
+ entries get tokens=None / in_context=None and the returned budget
429
+ reports available=False.
430
+ """
431
+ budget = ContextBudget()
432
+
433
+ estimate = getattr(agent, "estimate_tokens_for_message", None)
434
+ if not callable(estimate):
435
+ return budget
436
+
437
+ try:
438
+ context_length = int(agent._get_model_context_length())
439
+ except Exception:
440
+ context_length = 0
441
+
442
+ try:
443
+ overhead = int(agent._estimate_context_overhead())
444
+ except Exception:
445
+ overhead = 0
446
+
447
+ # Map history indices to raw messages for the estimator.
448
+ raw_by_idx = {i: msg for i, msg in enumerate(raw_history)}
449
+
450
+ # Per-entry token count
451
+ for entry in entries:
452
+ raw = raw_by_idx.get(entry.history_index)
453
+ if raw is None:
454
+ entry.tokens = None
455
+ continue
456
+ try:
457
+ entry.tokens = max(0, int(estimate(raw)))
458
+ except Exception:
459
+ entry.tokens = None
460
+ continue
461
+
462
+ # System messages are always sent; reserve their tokens before the
463
+ # contiguous non-system tail walk.
464
+ system_tokens = 0
465
+ for entry in entries:
466
+ if entry.role == "system" and entry.tokens is not None:
467
+ entry.in_context = True
468
+ system_tokens += entry.tokens
469
+
470
+ # Walk newest to oldest until the budget is exhausted; once one message
471
+ # overflows, all older messages are out of context.
472
+ available_budget = max(0, context_length - overhead - system_tokens)
473
+ non_system_cumulative = 0
474
+ out_of_context_total = 0
475
+ out_of_context_count = 0
476
+ overflowed = False
477
+ for entry in reversed(entries):
478
+ if entry.role == "system":
479
+ continue # already marked in_context=True above
480
+ if entry.tokens is None or context_length <= 0:
481
+ entry.in_context = None
482
+ continue
483
+ if not overflowed and non_system_cumulative + entry.tokens <= available_budget:
484
+ entry.in_context = True
485
+ non_system_cumulative += entry.tokens
486
+ else:
487
+ entry.in_context = False
488
+ overflowed = True
489
+ out_of_context_total += entry.tokens
490
+ out_of_context_count += 1
491
+
492
+ in_context_total = system_tokens + non_system_cumulative
493
+
494
+ # Report only the in-context tail in used_tokens; overflowed messages are
495
+ # separate so the percentage stays <=100%.
496
+ budget.used_tokens = in_context_total
497
+ budget.overhead_tokens = overhead
498
+ budget.context_length = context_length if context_length > 0 else None
499
+ budget.out_of_context_tokens = out_of_context_total
500
+ budget.out_of_context_messages = out_of_context_count
501
+ budget.available = context_length > 0
502
+ return budget
503
+
504
+
505
+ __all__ = [
506
+ "ContextBudget",
507
+ "MessageEntry",
508
+ "PruneSelection",
509
+ "Row",
510
+ "SIDE_EFFECT_ICONS",
511
+ "ToolCallInfo",
512
+ "annotate_context_window",
513
+ "build_message_entries",
514
+ "classify_tool",
515
+ "short_args",
516
+ "short_str",
517
+ ]