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,138 @@
1
+ """Register callbacks for the ``steer_queue`` plugin.
2
+
3
+ Mid-run Enter now QUEUES by default (see ``line_editor``); this plugin
4
+ supplies the rest of the feature:
5
+
6
+ * ``/steer <text>`` -- inject guidance mid-turn, interrupting the
7
+ agent's current train of thought ASAP (the old Enter default). At
8
+ idle it's a no-op with a hint: just type at the prompt.
9
+ * ``/queue`` -- full-screen queue manager with prompt preview, multiline
10
+ add/edit, guarded delete, and reordering. Works at idle and mid-run: both
11
+ paths already release the terminal around command execution.
12
+ * Status suffix -- a ``(N queued)`` tag rides the bottom bar's status
13
+ row, updated live via the PauseController's steer-queue listeners
14
+ (submit, drain, TUI edits -- every mutation fires them).
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ import logging
20
+ from typing import List, Optional, Tuple
21
+
22
+ from code_puppy.callbacks import register_callback
23
+
24
+ logger = logging.getLogger(__name__)
25
+
26
+ _STEER = "steer"
27
+ _QUEUE = "queue"
28
+
29
+
30
+ def _emit_info(message: str) -> None:
31
+ from code_puppy.messaging import emit_info
32
+
33
+ emit_info(message)
34
+
35
+
36
+ def _emit_warning(message: str) -> None:
37
+ from code_puppy.messaging import emit_warning
38
+
39
+ emit_warning(message)
40
+
41
+
42
+ # /steer
43
+ def _handle_steer(command: str) -> bool:
44
+ text = command.split(" ", 1)[1].strip() if " " in command else ""
45
+ if not text:
46
+ _emit_info("Usage: /steer <message> \u2014 inject guidance mid-turn")
47
+ return True
48
+
49
+ from code_puppy.messaging.run_ui import is_run_active
50
+
51
+ if not is_run_active():
52
+ _emit_warning(
53
+ "No agent run in flight \u2014 just type your prompt; "
54
+ "/steer only makes sense while the agent is working."
55
+ )
56
+ return True
57
+
58
+ from code_puppy.messaging.pause_controller import get_pause_controller
59
+
60
+ # ``mode='now'`` is announced by the history processor; no duplicate ack.
61
+ get_pause_controller().request_steer(text, mode="now")
62
+ return True
63
+
64
+
65
+ # /queue
66
+ def _handle_queue(command: str) -> bool:
67
+ from .queue_menu import open_queue_menu_blocking
68
+
69
+ open_queue_menu_blocking()
70
+ _emit_queue_summary()
71
+ return True
72
+
73
+
74
+ def _emit_queue_summary() -> None:
75
+ from code_puppy.messaging.pause_controller import get_pause_controller
76
+
77
+ count = len(get_pause_controller().peek_pending_steer_queued())
78
+ if count:
79
+ _emit_info(f"\u23ed {count} prompt(s) queued")
80
+ else:
81
+ _emit_info("Queue is empty")
82
+
83
+
84
+ # Status suffix: '(N queued)'
85
+ def _update_status_suffix(count: int) -> None:
86
+ """Steer-queue listener: paint/clear the pending-count tag.
87
+
88
+ ``count`` is the TOTAL across both queues (now + queued), so the
89
+ suffix is on whenever EITHER queue holds something. ``/steer`` uses
90
+ ``mode="now"``; that steer sits in the now-queue until the history
91
+ processor drains it, so the suffix tags the whole window between
92
+ submit and injection.
93
+ """
94
+ try:
95
+ from code_puppy.messaging.bottom_bar import get_bottom_bar
96
+
97
+ get_bottom_bar().set_status_suffix(f" ({count} pending)" if count else "")
98
+ except Exception:
99
+ logger.debug("pending-count paint failed", exc_info=True)
100
+
101
+
102
+ def _on_startup() -> None:
103
+ try:
104
+ from code_puppy.messaging.pause_controller import get_pause_controller
105
+
106
+ get_pause_controller().add_steer_queue_listener(_update_status_suffix)
107
+ except Exception:
108
+ logger.debug("steer_queue startup failed", exc_info=True)
109
+
110
+
111
+ # Registration
112
+ def _handle_custom_command(command: str, name: str) -> Optional[bool]:
113
+ if name == _STEER:
114
+ return _handle_steer(command)
115
+ if name == _QUEUE:
116
+ return _handle_queue(command)
117
+ return None
118
+
119
+
120
+ def _custom_help() -> List[Tuple[str, str]]:
121
+ return [
122
+ (_STEER, "Inject guidance mid-turn while the agent is running"),
123
+ (_QUEUE, "Manage queued prompts in a full-screen TUI"),
124
+ ]
125
+
126
+
127
+ register_callback("startup", _on_startup)
128
+ register_callback("custom_command", _handle_custom_command)
129
+ register_callback("custom_command_help", _custom_help)
130
+
131
+
132
+ __all__ = [
133
+ "_handle_custom_command",
134
+ "_handle_queue",
135
+ "_handle_steer",
136
+ "_on_startup",
137
+ "_update_status_suffix",
138
+ ]
@@ -0,0 +1,102 @@
1
+ # subagent_panel
2
+
3
+ A live, two-line status block for each running sub-agent, painted just above the
4
+ bouncing puppy:
5
+
6
+ ```
7
+ INVOKE AGENT pup-ticket-investigator claude-4-8-opus
8
+ (spin) 00:19 calling read_file
9
+ INVOKE AGENT pup-analysis-adjudicator
10
+ (spin) 00:25 calling grep
11
+
12
+ Milo is thinking... ( o )
13
+ ```
14
+
15
+ - Line 1 is the `INVOKE AGENT` banner (same color/styling as core).
16
+ - Line 2 is a single-char animated spinner + `mm:ss` elapsed + the current
17
+ activity, color-coded: **yellow** = calling a tool, **magenta** = thinking,
18
+ **green** = writing the response.
19
+ - Parallel sub-agents stack, each with its own live row. There is no arbitrary
20
+ cap: every tracked agent renders as long as it fits. The row count is only
21
+ clamped to the terminal height (the prompt + status always keep their rows) --
22
+ if a swarm is taller than the viewport, the rows that don't fit collapse into a
23
+ single `… +N more` summary rather than blanking the whole bar.
24
+ - **Nested sub-agents render as a true tree.** A sub-agent that itself calls
25
+ `invoke_agent` is shown indented under its parent. Only top-level (depth-0)
26
+ agents get the full two-line `INVOKE AGENT` banner; deeper agents collapse to
27
+ a compact one-liner -- `<elbow> name mm:ss purpose model` -- so the banner
28
+ text + model label aren't repeated at every level:
29
+
30
+ ```
31
+ INVOKE AGENT regression-runner gpt-5.5
32
+ (spin) 00:12 calling invoke_agent
33
+ \u2514\u2500 pup-ticket-investigator 00:12 calling read_file claude-4-8-opus
34
+ \u2514\u2500 deep-helper 00:12 thinking... gpt-5.5-mini
35
+ ```
36
+
37
+ The parent link is captured at emit time from an async-safe `ContextVar`
38
+ (`_PARENT_SID`), NOT the bus's single global `_current_session_id`. The
39
+ global is shared across all asyncio tasks, so two `invoke_agent` calls running
40
+ concurrently would clobber it and mis-parent one root under the other (a bogus
41
+ deep chain). A `ContextVar` is copied into each task at `create_task` time, so
42
+ concurrent siblings each see their own correct parent -- see
43
+ `_install_parent_tracking` (mirrors `set_session_context`) + `_install_emit_hook`.
44
+ - **On completion** the block doesn't just vanish: a persistent frozen record
45
+ is printed to the transcript mirroring the live look, with line 2 finalized
46
+ as a green check + `mm:ss completed`:
47
+
48
+ ```
49
+ INVOKE AGENT pup-ticket-investigator claude-4-8-opus
50
+ (check) 00:45 completed
51
+ ```
52
+
53
+ (The redundant core "<check> <name> completed successfully" line is suppressed.)
54
+ Nested agents get a compact one-liner frozen record instead of the full block:
55
+ `<elbow> name (check) mm:ss completed model`.
56
+
57
+ ## How it works (3 monkeypatches, 1 callback -- no core edits)
58
+
59
+ The puppy spinner already runs a Rich `Live` that repaints ~20x/second. Rather
60
+ than spin up a second `Live` (which fights the puppy's -- the reason the
61
+ built-in `SubAgentConsoleManager` is dead code), this plugin reuses it:
62
+
63
+ 1. **`ConsoleSpinner._generate_spinner_panel`** -> returns
64
+ `Group(status block..., "", puppy)` so the existing loop renders everything.
65
+ 2. **`RichConsoleRenderer._render_subagent_invocation`** -> *captures* the exact
66
+ metadata (name / session_type / model / **session_id**) and *suppresses* the
67
+ permanent banner. The live block now owns the banner, so there's no
68
+ duplicate, and registration is exact even for parallel sub-agents (no
69
+ session-id guessing).
70
+ 3. **`RichConsoleRenderer._do_render`** -> when the `SubAgentResponseMessage`
71
+ arrives (core skips it), print the persistent frozen two-line record + pop
72
+ the live row, and suppress the redundant completion-text line.
73
+
74
+ Status text is fed by the **`stream_event`** callback, keyed by `session_id`.
75
+ `record_event` is *update-only*: an event for an unregistered session is ignored,
76
+ which cleanly filters out the main agent's own stream events. `coalesce_patch.py`
77
+ batches sub-agent stream-event callbacks (~50ms) so parallel token streams do
78
+ not starve the steer overlay's event-loop continuations.
79
+
80
+ ## Config
81
+
82
+ Runtime toggle:
83
+
84
+ ```text
85
+ /set subagent_panel off
86
+ /set subagent_panel on
87
+ ```
88
+
89
+ Environment startup hard-disable:
90
+
91
+ | Var | Default | Meaning |
92
+ |-----|---------|---------|
93
+ | DISABLE_SUBAGENT_PANEL | unset | Set 1 to skip registration entirely |
94
+ | SUBAGENT_PANEL | 1 | Set 0 to skip registration entirely |
95
+ | SUBAGENT_PANEL_IDLE_S | 600 | Prune after this many idle seconds (safety net) |
96
+
97
+ ## Notes
98
+
99
+ - Installs wrappers at **startup**, but `/set subagent_panel off` makes them pass through live.
100
+ - The permanent invocation banner (with Prompt/Session) is intentionally
101
+ replaced by the transient live block; on completion a compact frozen
102
+ two-line record (banner + green check) is left in the transcript.
@@ -0,0 +1,24 @@
1
+ """subagent_panel -- live two-line status per sub-agent above the puppy.
2
+
3
+ Renders, inside the puppy spinner's own Rich Live region, a block per active
4
+ sub-agent::
5
+
6
+ INVOKE AGENT <name> <model>
7
+ <spin> 00:19 calling read_file
8
+
9
+ <bouncing puppy>
10
+
11
+ Line 1 is the INVOKE AGENT banner (core styling); line 2 is a single-char
12
+ animated spinner + mm:ss elapsed + a color-coded status (yellow=calling,
13
+ magenta=thinking, green=writing). Parallel sub-agents stack.
14
+
15
+ It reuses the puppy spinner's existing Rich ``Live`` (a monkeypatch of
16
+ ``_generate_spinner_panel``) rather than a second ``Live`` -- two Live displays
17
+ on one console fight each other (which is why the built-in, fully-built but
18
+ never-wired ``SubAgentConsoleManager`` was dead code). Exact per-agent metadata
19
+ is captured by monkeypatching ``_render_subagent_invocation`` (which also
20
+ suppresses the now-redundant permanent banner). On completion, ``_do_render``
21
+ is wrapped to print a persistent frozen two-line record (banner + green check +
22
+ mm:ss completed) and suppress the redundant core completion line. Status text is
23
+ fed by the ``stream_event`` callback. See register_callbacks.py + state.py.
24
+ """
@@ -0,0 +1,242 @@
1
+ """Coalesce sub-agent stream_event callbacks from a user plugin.
2
+
3
+ PUP-301 briefly patched ``code_puppy.agents.subagent_stream_handler`` in core so
4
+ parallel sub-agents don't create one asyncio task per streamed token. That fixed
5
+ Ctrl+T steer-overlay lag under a sub-agent swarm, but the feature belongs in the
6
+ user plugin while this experiment stays out of the repo.
7
+
8
+ This module installs the same behavior as a small monkeypatch:
9
+
10
+ * replace ``subagent_stream_handler._fire_callback`` with a batched version;
11
+ * wrap ``subagent_stream_handler.subagent_stream_handler`` so stream-end flushes
12
+ any trailing events (especially ``part_end``);
13
+ * pass through to the original callback whenever ``subagent_panel`` is
14
+ runtime-disabled via ``/set subagent_panel off``.
15
+
16
+ All state is event-loop local in practice: core calls this from the stream
17
+ handler running on the main loop. No locks, no cute cleverness. Cute cleverness
18
+ is how puppies end up inside washing machines.
19
+ """
20
+
21
+ from __future__ import annotations
22
+
23
+ import asyncio
24
+ import importlib
25
+ import logging
26
+ import time
27
+ from collections.abc import Awaitable, Callable
28
+ from typing import Any, Optional
29
+
30
+ logger = logging.getLogger(__name__)
31
+
32
+ COALESCE_INTERVAL_S: float = 0.050
33
+ _MARKER = "_subagent_panel_coalesced"
34
+
35
+ Event = tuple[str, Any, Optional[str]]
36
+ EnabledChecker = Callable[[], bool]
37
+ FireCallback = Callable[[str, Any, Optional[str]], None]
38
+
39
+ _pending_events: list[Event] = []
40
+ _drain_scheduled = False
41
+ _last_drain_time = 0.0
42
+ _original_fire_callback: FireCallback | None = None
43
+ _original_stream_handler: Callable[..., Awaitable[None]] | None = None
44
+ _enabled_checker: EnabledChecker | None = None
45
+
46
+
47
+ def _enabled() -> bool:
48
+ if _enabled_checker is None:
49
+ return True
50
+ try:
51
+ return bool(_enabled_checker())
52
+ except Exception:
53
+ return True
54
+
55
+
56
+ def _fire_original(event_type: str, event_data: Any, session_id: Optional[str]) -> None:
57
+ original = _original_fire_callback
58
+ if original is None:
59
+ return
60
+ try:
61
+ original(event_type, event_data, session_id)
62
+ except Exception as exc: # noqa: BLE001 - callback plumbing must not explode
63
+ logger.debug("Original stream_event callback failed: %s", exc)
64
+
65
+
66
+ def _coalesced_fire_callback(
67
+ event_type: str,
68
+ event_data: Any,
69
+ session_id: Optional[str],
70
+ ) -> None:
71
+ """Queue a stream-event callback for batched delivery.
72
+
73
+ When runtime-disabled, this delegates to the exact original core callback so
74
+ ``/set subagent_panel off`` really behaves like vanilla Code Puppy.
75
+ """
76
+ global _drain_scheduled, _last_drain_time
77
+
78
+ if not _enabled():
79
+ _fire_original(event_type, event_data, session_id)
80
+ return
81
+
82
+ _pending_events.append((event_type, event_data, session_id))
83
+ if _drain_scheduled:
84
+ return
85
+
86
+ try:
87
+ loop = asyncio.get_running_loop()
88
+ except RuntimeError:
89
+ clear_pending()
90
+ return
91
+
92
+ now = time.monotonic()
93
+ elapsed = now - _last_drain_time
94
+ _drain_scheduled = True
95
+ if elapsed >= COALESCE_INTERVAL_S:
96
+ loop.call_soon(_drain_pending_task, loop)
97
+ else:
98
+ loop.call_later(COALESCE_INTERVAL_S - elapsed, _drain_pending_task, loop)
99
+
100
+
101
+ def _drain_pending_task(loop: asyncio.AbstractEventLoop) -> None:
102
+ """Drain pending events as one scheduled asyncio task."""
103
+ global _drain_scheduled, _last_drain_time
104
+
105
+ _drain_scheduled = False
106
+ _last_drain_time = time.monotonic()
107
+ if not _pending_events:
108
+ return
109
+
110
+ batch = list(_pending_events)
111
+ _pending_events.clear()
112
+ loop.create_task(_fire_batch(batch))
113
+
114
+
115
+ async def _fire_batch(batch: list[Event]) -> None:
116
+ try:
117
+ from code_puppy import callbacks
118
+ except ImportError:
119
+ logger.debug("Callbacks module not available for stream event")
120
+ return
121
+
122
+ for event_type, event_data, session_id in batch:
123
+ try:
124
+ await callbacks.on_stream_event(event_type, event_data, session_id)
125
+ except Exception as exc: # noqa: BLE001 - match core's fail-safe behavior
126
+ logger.debug("Error in stream_event callback: %s", exc)
127
+
128
+
129
+ async def flush_pending_callbacks() -> None:
130
+ """Synchronously drain any queued events.
131
+
132
+ The stream-handler wrapper calls this in ``finally`` so terminal events do
133
+ not sit behind the coalesce timer after a sub-agent stream completes.
134
+ """
135
+ global _drain_scheduled, _last_drain_time
136
+
137
+ _drain_scheduled = False
138
+ _last_drain_time = time.monotonic()
139
+ if not _pending_events:
140
+ return
141
+
142
+ batch = list(_pending_events)
143
+ _pending_events.clear()
144
+ await _fire_batch(batch)
145
+
146
+
147
+ def clear_pending() -> None:
148
+ """Drop pending events without firing them; used only for abnormal no-loop paths."""
149
+ global _drain_scheduled
150
+
151
+ _pending_events.clear()
152
+ _drain_scheduled = False
153
+
154
+
155
+ def _make_stream_handler_wrapper(original: Callable[..., Awaitable[None]]):
156
+ async def _wrapped(*args: Any, **kwargs: Any) -> None:
157
+ try:
158
+ await original(*args, **kwargs)
159
+ finally:
160
+ await flush_pending_callbacks()
161
+
162
+ setattr(_wrapped, _MARKER, True)
163
+ setattr(_wrapped, "_subagent_panel_original_stream_handler", original)
164
+ return _wrapped
165
+
166
+
167
+ def install(enabled_checker: EnabledChecker | None = None) -> bool:
168
+ """Install the coalescing monkeypatch idempotently.
169
+
170
+ Returns ``True`` when installed/already installed, ``False`` if the core
171
+ module is not importable. Import failure is okay during lightweight tests.
172
+ """
173
+ global _enabled_checker, _original_fire_callback, _original_stream_handler
174
+
175
+ _enabled_checker = enabled_checker
176
+ try:
177
+ module = importlib.import_module("code_puppy.agents.subagent_stream_handler")
178
+ except Exception as exc: # noqa: BLE001 - plugin startup must be best-effort
179
+ logger.debug("Could not import subagent_stream_handler: %s", exc)
180
+ return False
181
+
182
+ current_fire = getattr(module, "_fire_callback", None)
183
+ if current_fire is None:
184
+ return False
185
+ if not getattr(current_fire, _MARKER, False):
186
+ _original_fire_callback = current_fire
187
+ setattr(_coalesced_fire_callback, _MARKER, True)
188
+ setattr(
189
+ _coalesced_fire_callback,
190
+ "_subagent_panel_original_fire_callback",
191
+ current_fire,
192
+ )
193
+ module._fire_callback = _coalesced_fire_callback
194
+ elif _original_fire_callback is None:
195
+ _original_fire_callback = getattr(
196
+ current_fire, "_subagent_panel_original_fire_callback", None
197
+ )
198
+
199
+ current_handler = getattr(module, "subagent_stream_handler", None)
200
+ if current_handler is None:
201
+ return True
202
+ if not getattr(current_handler, _MARKER, False):
203
+ _original_stream_handler = current_handler
204
+ module.subagent_stream_handler = _make_stream_handler_wrapper(current_handler)
205
+ elif _original_stream_handler is None:
206
+ _original_stream_handler = getattr(
207
+ current_handler, "_subagent_panel_original_stream_handler", None
208
+ )
209
+
210
+ return True
211
+
212
+
213
+ def uninstall() -> None:
214
+ """Restore original core callables when this plugin owns the patch."""
215
+ global _original_fire_callback, _original_stream_handler, _enabled_checker
216
+
217
+ try:
218
+ module = importlib.import_module("code_puppy.agents.subagent_stream_handler")
219
+ except Exception:
220
+ clear_pending()
221
+ return
222
+
223
+ if getattr(getattr(module, "_fire_callback", None), _MARKER, False):
224
+ if _original_fire_callback is not None:
225
+ module._fire_callback = _original_fire_callback
226
+ if getattr(getattr(module, "subagent_stream_handler", None), _MARKER, False):
227
+ if _original_stream_handler is not None:
228
+ module.subagent_stream_handler = _original_stream_handler
229
+
230
+ clear_pending()
231
+ _original_fire_callback = None
232
+ _original_stream_handler = None
233
+ _enabled_checker = None
234
+
235
+
236
+ __all__ = [
237
+ "COALESCE_INTERVAL_S",
238
+ "clear_pending",
239
+ "flush_pending_callbacks",
240
+ "install",
241
+ "uninstall",
242
+ ]
@@ -0,0 +1,145 @@
1
+ """Rendering helpers for the sub-agent panel (live rows + transcript).
2
+
3
+ Pure presentation: tree ordering, model-name shorthand, and the aligned
4
+ one-line-per-agent row renderer shared by the live bottom-bar panel and
5
+ the frozen transcript records. No I/O, no state mutation — that lives in
6
+ ``register_callbacks`` / ``state``.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+
12
+ from . import state
13
+
14
+
15
+ def _banner_color():
16
+ try:
17
+ from code_puppy.config import get_banner_color
18
+
19
+ return get_banner_color("invoke_agent")
20
+ except Exception:
21
+ return "blue"
22
+
23
+
24
+ # Hierarchy helpers (true parent -> child tree)
25
+ def _ordered_tree(rows):
26
+ """Return [(entry, depth), ...] in DFS order. A row whose parent is not in
27
+ the set (e.g. the main agent, or None) is a root (depth 0); descendants are
28
+ indented one-liners. Cycle-safe; stable by start time."""
29
+ by_id = {e["session_id"]: e for e in rows if e.get("session_id")}
30
+ children = {}
31
+ roots = []
32
+ for e in rows:
33
+ p = e.get("parent")
34
+ if p and p in by_id:
35
+ children.setdefault(p, []).append(e)
36
+ else:
37
+ roots.append(e)
38
+ out = []
39
+ seen = set()
40
+
41
+ def walk(node, depth):
42
+ sid = node.get("session_id")
43
+ if sid in seen:
44
+ return
45
+ seen.add(sid)
46
+ out.append((node, depth))
47
+ for kid in sorted(children.get(sid, []), key=lambda c: c["start"]):
48
+ walk(kid, depth + 1)
49
+
50
+ for r in sorted(roots, key=lambda e: e["start"]):
51
+ walk(r, 0)
52
+ return out
53
+
54
+
55
+ def _model_short(model):
56
+ """Return the model identifier verbatim for the panel display.
57
+
58
+ Deliberately a passthrough: whatever the user picked with ``/model <key>``
59
+ is what shows up in the subagent panel. No parsing, no title-casing, no
60
+ tier/env extraction -- previous versions built a curated shorthand from
61
+ a hard-coded allowlist of tier tokens (nano/mini/flash/...) plus an env
62
+ allowlist ('stage'), which silently dropped any suffix outside the lists
63
+ (e.g. -stage). Users would rather see the raw config key and trust their
64
+ own eyes; that also removes an allowlist maintenance chore forever.
65
+ Empty / None inputs collapse to an empty string so the panel column
66
+ doesn't render the literal 'None'.
67
+ """
68
+ return str(model) if model else ""
69
+
70
+
71
+ def _row_lines(ordered, frame):
72
+ """Render a list of (entry, depth) as aligned single-line rows:
73
+ <prefix><name> <model> <spin|check> <mm:ss>
74
+ The model + indicator + time columns share a per-tree tab-stop computed
75
+ from the widest (prefix+name) AND the widest model label, so longer model
76
+ names (e.g. 'GPT 5.4-Nano') and deeper-indented names both push the whole
77
+ right block over together -- columns stay aligned no matter what gets added.
78
+ Alignment is done purely with U+0020 spaces (never literal tabs), and widths
79
+ use Rich cell_len, so the layout renders identically on Windows and macOS.
80
+ Root rows carry the INVOKE AGENT badge; nested rows carry the tree elbow.
81
+ Used for BOTH the live block and the transcript.
82
+ """
83
+ from rich.cells import cell_len
84
+ from rich.text import Text
85
+
86
+ color = _banner_color()
87
+ lefts = []
88
+ models = []
89
+ name_w = 0
90
+ model_w = 0
91
+ for e, depth in ordered:
92
+ left = Text(no_wrap=True, overflow="ellipsis")
93
+ if depth == 0:
94
+ left.append(" \U0001f916 INVOKE AGENT ", style=f"bold white on {color}")
95
+ left.append(" ")
96
+ left.append(e["name"], style="bold cyan")
97
+ else:
98
+ left.append(" " + " " * (depth - 1))
99
+ left.append("\u2514\u2500 ", style="grey50") # tree elbow
100
+ left.append(e["name"], style="bold cyan")
101
+ lefts.append(left)
102
+ ms = _model_short(e.get("model"))
103
+ models.append(ms)
104
+ name_w = max(name_w, left.cell_len)
105
+ model_w = max(model_w, cell_len(ms))
106
+
107
+ lines = []
108
+ for (e, depth), left, ms in zip(ordered, lefts, models):
109
+ done = bool(e.get("done"))
110
+ failed = bool(e.get("failed"))
111
+ line = left.copy()
112
+ # Keep status rows single-line; crop visually for the terminal but retain
113
+ # full status in state.
114
+ line.no_wrap = True
115
+ line.overflow = "ellipsis"
116
+ line.append(" " * (name_w - left.cell_len + 2))
117
+ line.append(ms, style="magenta")
118
+ line.append(" " * (model_w - cell_len(ms) + 2))
119
+ if failed:
120
+ line.append("\u2717 ", style="bold red") # X mark
121
+ elif done:
122
+ line.append("\u2713 ", style="bold green") # check
123
+ else:
124
+ line.append((frame or " ") + " ", style="bold cyan")
125
+ line.append(state.fmt_elapsed_entry(e), style="dim")
126
+ # Current action / status, color-coded (yellow=calling, magenta=thinking,
127
+ # green=writing). Done rows show 'completed' green; failed rows 'failed' red.
128
+ status = e.get("status", "starting")
129
+ line.append(" ")
130
+ if failed:
131
+ line.append("failed", style="bold red")
132
+ elif done:
133
+ line.append("completed", style="green")
134
+ else:
135
+ line.append(status, style=state.status_style(status))
136
+ lines.append(line)
137
+ return lines
138
+
139
+
140
+ __all__ = [
141
+ "_banner_color",
142
+ "_model_short",
143
+ "_ordered_tree",
144
+ "_row_lines",
145
+ ]