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,460 @@
1
+ """GitHub Copilot auth plugin — callback registrations.
2
+
3
+ Provides:
4
+ - ``/copilot-login`` — browser-based GitHub Device Flow auth
5
+ - ``/copilot-status`` — show auth & model status
6
+ - ``/copilot-logout`` — remove tokens and registered Copilot models
7
+ - ``copilot`` model-type handler for ``model_factory``
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import logging
13
+ from typing import Any, Dict, List, Optional, Tuple
14
+
15
+ from code_puppy.callbacks import register_callback
16
+ from code_puppy.messaging import emit_error, emit_info, emit_success, emit_warning
17
+
18
+ from .config import COPILOT_AUTH_CONFIG
19
+ from .utils import (
20
+ add_models_to_config,
21
+ clear_caches,
22
+ fetch_copilot_models,
23
+ get_api_endpoint_for_host,
24
+ get_token_for_host,
25
+ get_valid_session_token,
26
+ load_copilot_models,
27
+ load_device_tokens,
28
+ poll_for_token,
29
+ remove_copilot_models,
30
+ save_device_token,
31
+ start_device_flow,
32
+ )
33
+
34
+ logger = logging.getLogger(__name__)
35
+
36
+
37
+ # ---------------------------------------------------------------------------
38
+ # /help entries
39
+ # ---------------------------------------------------------------------------
40
+
41
+
42
+ def _custom_help() -> List[Tuple[str, str]]:
43
+ return [
44
+ (
45
+ "copilot-login",
46
+ "Authenticate with GitHub/GitHub Enterprise Copilot via browser",
47
+ ),
48
+ ("copilot-status", "Show GitHub Copilot authentication status and models"),
49
+ ("copilot-logout", "Remove Copilot tokens and registered models"),
50
+ ]
51
+
52
+
53
+ # ---------------------------------------------------------------------------
54
+ # /copilot-status
55
+ # ---------------------------------------------------------------------------
56
+
57
+
58
+ def _handle_copilot_status() -> None:
59
+ tokens = load_device_tokens()
60
+
61
+ if not tokens:
62
+ emit_warning(
63
+ "🔓 GitHub Copilot: Not authenticated.\n"
64
+ " Run /copilot-login to sign in via your browser."
65
+ )
66
+ return
67
+
68
+ emit_success("🔐 GitHub Copilot: Authenticated")
69
+ for t in tokens:
70
+ host_label = t.host
71
+ user_label = f" ({t.user})" if t.user else ""
72
+ emit_info(f" • {host_label}{user_label}")
73
+
74
+ # Check session token for each host
75
+ for t in tokens:
76
+ session = get_valid_session_token(t.oauth_token, t.host)
77
+ if session:
78
+ emit_info(f" ✅ {t.host}: active session (auto-refreshes on expiry)")
79
+ else:
80
+ emit_warning(
81
+ f" ⚠️ {t.host}: could not obtain a session token — may be expired"
82
+ )
83
+ emit_info(f" Run /copilot-login {t.host} to re-authenticate.")
84
+
85
+ # Registered models
86
+ models = load_copilot_models()
87
+ copilot_models = [
88
+ name
89
+ for name, cfg in models.items()
90
+ if cfg.get("oauth_source") == "copilot-auth-plugin"
91
+ ]
92
+ if copilot_models:
93
+ emit_info(f"🎯 Registered Copilot models: {', '.join(sorted(copilot_models))}")
94
+ else:
95
+ emit_warning(
96
+ "⚠️ No Copilot models registered yet. Run /copilot-login to set up."
97
+ )
98
+
99
+
100
+ # ---------------------------------------------------------------------------
101
+ # /copilot-logout
102
+ # ---------------------------------------------------------------------------
103
+
104
+
105
+ def _handle_copilot_logout() -> None:
106
+ errors: list[str] = []
107
+
108
+ # 1. Remove registered models from copilot_models.json
109
+ removed = remove_copilot_models()
110
+ if removed:
111
+ emit_info(f"Removed {removed} Copilot model(s) from configuration")
112
+ else:
113
+ emit_info("No Copilot models were registered")
114
+
115
+ # 2. Delete on-disk token/session caches
116
+ from .config import get_device_token_storage_path, get_session_cache_path
117
+
118
+ for path in (get_session_cache_path(), get_device_token_storage_path()):
119
+ if path.exists():
120
+ try:
121
+ path.unlink()
122
+ except Exception as exc:
123
+ errors.append(f"Could not remove {path.name}: {exc}")
124
+
125
+ # 3. Clear in-memory session and endpoint caches
126
+ clear_caches()
127
+
128
+ # 4. If the active model was a copilot model, reset it so the app
129
+ # doesn't keep trying to use a model whose tokens are gone.
130
+ try:
131
+ from code_puppy.config import (
132
+ clear_model_cache,
133
+ get_model_name,
134
+ reset_session_model,
135
+ )
136
+
137
+ current = get_model_name()
138
+ if current and current.startswith(COPILOT_AUTH_CONFIG["prefix"]):
139
+ reset_session_model()
140
+ clear_model_cache()
141
+ emit_info(f"Reset active model (was {current})")
142
+ except Exception:
143
+ pass # Non-critical — worst case the next prompt will error and user switches
144
+
145
+ # 5. Report outcome
146
+ if errors:
147
+ for err in errors:
148
+ emit_warning(err)
149
+ emit_warning("Copilot logout completed with errors (see above)")
150
+ else:
151
+ emit_success("Copilot logout complete — all tokens removed")
152
+
153
+
154
+ # ---------------------------------------------------------------------------
155
+ # /copilot-login — browser-based GitHub Device Flow
156
+ # ---------------------------------------------------------------------------
157
+
158
+
159
+ def _normalize_github_host(raw_host: str) -> str | None:
160
+ """Validate and normalize a GitHub hostname for safe URL interpolation.
161
+
162
+ The hostname is interpolated into URLs like
163
+ ``https://{host}/login/device/code``, so we must reject anything that
164
+ could alter the URL structure (schemes, paths, credentials, etc.).
165
+
166
+ Returns:
167
+ The cleaned lowercase hostname on success, or ``None`` if the input
168
+ is invalid.
169
+
170
+ Rejects inputs containing:
171
+ - URL schemes (``://``) — e.g. ``https://evil.com``
172
+ - Path segments (``/``, ``\\``) — e.g. ``github.com/evil``
173
+ - Credentials (``@``) — e.g. ``user@attacker.tld``
174
+ - Query strings (``?``) — e.g. ``host?q=1``
175
+ - Fragments (``#``) — e.g. ``host#frag``
176
+ """
177
+ host = raw_host.strip().lower()
178
+ if not host:
179
+ return "github.com"
180
+
181
+ # Block characters that would alter URL structure when interpolated
182
+ unsafe_chars = ("://", "/", "\\", "@", "?", "#")
183
+ for marker in unsafe_chars:
184
+ if marker in host:
185
+ return None
186
+
187
+ # Strip trailing dots (DNS allows them but they're not meaningful here)
188
+ return host.rstrip(".")
189
+
190
+
191
+ def _handle_copilot_login(command: str) -> None:
192
+ """Authenticate with GitHub Copilot via the GitHub Device Flow.
193
+
194
+ Opens a browser for the user to enter a one-time code. Supports
195
+ GitHub Enterprise by passing the hostname:
196
+ ``/copilot-login ghes.example.com``
197
+
198
+ When no hostname is given the user is prompted (default: github.com).
199
+ """
200
+ # Parse optional GHE hostname from command arguments
201
+ parts = command.strip().split()
202
+ host: str | None = None
203
+ if len(parts) > 1:
204
+ host = parts[1].strip()
205
+
206
+ # If no host was provided as an argument, prompt the user
207
+ if not host:
208
+ emit_info(
209
+ "🌐 Enter your GitHub hostname — just the domain, no https:// or path.\n"
210
+ " Examples: github.com, ghe.mycompany.com\n"
211
+ " Press Enter to use github.com."
212
+ )
213
+ try:
214
+ from prompt_toolkit import prompt as pt_prompt
215
+
216
+ raw = pt_prompt("GitHub host: ", default="github.com").strip()
217
+ host = raw if raw else "github.com"
218
+ except ImportError:
219
+ host = "github.com"
220
+ except (EOFError, KeyboardInterrupt):
221
+ emit_warning("Copilot login cancelled.")
222
+ return
223
+
224
+ # Validate the hostname before interpolating it into any URLs
225
+ host = _normalize_github_host(host)
226
+ if not host:
227
+ emit_error(
228
+ "Invalid hostname — expected a bare domain like github.com or ghe.mycompany.com.\n"
229
+ " Do not include https://, paths, or special characters."
230
+ )
231
+ return
232
+
233
+ if host != "github.com":
234
+ emit_info(f"Using GitHub Enterprise host: {host}")
235
+
236
+ emit_info(f"🔑 Starting GitHub Device Flow for {host}…")
237
+
238
+ device_resp = start_device_flow(host)
239
+ if not device_resp:
240
+ emit_error(
241
+ "Failed to start Device Flow. Check your network connection "
242
+ "and ensure the host is reachable."
243
+ )
244
+ return
245
+
246
+ user_code = device_resp["user_code"]
247
+ verification_uri = device_resp.get(
248
+ "verification_uri", f"https://{host}/login/device"
249
+ )
250
+ expires_in = int(device_resp.get("expires_in", 900))
251
+ interval = int(device_resp.get("interval", 5))
252
+
253
+ # Show the code prominently
254
+ emit_success(f"🔗 Your one-time code: {user_code}")
255
+ emit_info(f" Open {verification_uri} and enter the code above.")
256
+
257
+ # Try to open the browser
258
+ try:
259
+ import webbrowser
260
+
261
+ from code_puppy.tools.common import should_suppress_browser
262
+
263
+ if should_suppress_browser():
264
+ emit_info(f"[HEADLESS MODE] Visit: {verification_uri}")
265
+ else:
266
+ webbrowser.open(verification_uri)
267
+ except Exception as exc:
268
+ logger.debug("Could not open browser: %s", exc)
269
+ emit_info(f"Please open this URL manually: {verification_uri}")
270
+
271
+ emit_info("⏳ Waiting for you to authorize in the browser…")
272
+
273
+ oauth_token = poll_for_token(
274
+ device_code=device_resp["device_code"],
275
+ host=host,
276
+ interval=interval,
277
+ expires_in=expires_in,
278
+ )
279
+
280
+ if not oauth_token:
281
+ emit_error(
282
+ "Authorization was not completed in time, or was denied. "
283
+ "Please try /copilot-login again."
284
+ )
285
+ return
286
+
287
+ emit_success("✅ GitHub authorization successful!")
288
+
289
+ # Persist the token
290
+ if not save_device_token(host, oauth_token):
291
+ emit_warning("Token obtained but could not be saved to disk.")
292
+
293
+ # Exchange for Copilot session token & register models
294
+ emit_info("Exchanging for Copilot session token…")
295
+ session = get_valid_session_token(oauth_token, host)
296
+ if not session:
297
+ emit_warning(
298
+ "Got a GitHub token but could not obtain a Copilot session token.\n"
299
+ " Your GitHub account may not have Copilot access."
300
+ )
301
+ return
302
+
303
+ emit_success("✅ Copilot session token obtained")
304
+
305
+ emit_info("Fetching available Copilot models…")
306
+ model_list = fetch_copilot_models(session, host)
307
+ if model_list and add_models_to_config(model_list, host):
308
+ emit_success(
309
+ f"Registered {len(model_list)} Copilot model(s). "
310
+ "Use the `copilot-` prefix with /model."
311
+ )
312
+ try:
313
+ from code_puppy.model_switching import set_model_and_reload_agent
314
+
315
+ default_model = f"{COPILOT_AUTH_CONFIG['prefix']}{model_list[0]}"
316
+ set_model_and_reload_agent(default_model)
317
+ except Exception as exc:
318
+ logger.debug("Could not auto-switch to Copilot model: %s", exc)
319
+ else:
320
+ emit_warning("Could not register Copilot models.")
321
+
322
+
323
+ # ---------------------------------------------------------------------------
324
+ # custom_command dispatcher
325
+ # ---------------------------------------------------------------------------
326
+
327
+
328
+ def _handle_custom_command(command: str, name: str) -> Optional[bool]:
329
+ if not name:
330
+ return None
331
+ if name == "copilot-login":
332
+ _handle_copilot_login(command)
333
+ return True
334
+ if name == "copilot-status":
335
+ _handle_copilot_status()
336
+ return True
337
+ if name == "copilot-logout":
338
+ _handle_copilot_logout()
339
+ return True
340
+ return None
341
+
342
+
343
+ # ---------------------------------------------------------------------------
344
+ # Model-type handler — creates OpenAI-compatible model for Copilot API
345
+ # ---------------------------------------------------------------------------
346
+
347
+
348
+ def _create_copilot_model(model_name: str, model_config: Dict, config: Dict) -> Any:
349
+ """Create an OpenAI-compatible model backed by GitHub Copilot API.
350
+
351
+ Called by ``model_factory`` when ``type == "copilot"``.
352
+
353
+ Uses a dynamic auth flow that refreshes the short-lived Copilot session
354
+ token automatically before each API request, preventing mid-conversation
355
+ token expiry errors.
356
+ """
357
+ import httpx
358
+ from pydantic_ai.models.openai import OpenAIChatModel
359
+ from pydantic_ai.providers.openai import OpenAIProvider
360
+
361
+ from code_puppy.http_utils import create_async_client
362
+
363
+ # Discover token — match against the host stored in the model config
364
+ host = model_config.get("copilot_host", "github.com")
365
+ preferred = get_token_for_host(host)
366
+ if not preferred:
367
+ emit_warning(
368
+ f"No Copilot token available for host '{host}'; skipping model '{model_config.get('name')}'. "
369
+ "Run /copilot-login first."
370
+ )
371
+ return None
372
+
373
+ # Verify we can get an initial session token
374
+ session_token = get_valid_session_token(preferred.oauth_token, preferred.host)
375
+ if not session_token:
376
+ emit_warning(
377
+ f"Could not obtain Copilot session token; skipping model '{model_config.get('name')}'. "
378
+ "Run /copilot-login to re-authenticate."
379
+ )
380
+ return None
381
+
382
+ # Client with Copilot-required headers + per-request token refresh: _CopilotAuth
383
+ # swaps the Authorization header every request, keeping long convos fresh.
384
+ copilot_headers = {
385
+ "Editor-Version": COPILOT_AUTH_CONFIG["editor_version"],
386
+ "Editor-Plugin-Version": COPILOT_AUTH_CONFIG["editor_plugin_version"],
387
+ "Copilot-Integration-Id": COPILOT_AUTH_CONFIG["copilot_integration_id"],
388
+ "Openai-Intent": COPILOT_AUTH_CONFIG["openai_intent"],
389
+ }
390
+
391
+ class _CopilotAuth(httpx.Auth):
392
+ """httpx auth flow that refreshes the Copilot session token per-request."""
393
+
394
+ def __init__(self, oauth_token: str, token_host: str):
395
+ self._oauth_token = oauth_token
396
+ self._host = token_host
397
+
398
+ def auth_flow(self, request: httpx.Request):
399
+ token = get_valid_session_token(self._oauth_token, self._host)
400
+ if token:
401
+ request.headers["Authorization"] = f"Bearer {token}"
402
+ yield request
403
+
404
+ client = create_async_client(headers=copilot_headers)
405
+ # Attach the dynamic auth so every request gets a fresh token
406
+ client.auth = _CopilotAuth(preferred.oauth_token, preferred.host)
407
+
408
+ # Use the API endpoint discovered during session-token exchange.
409
+ # Falls back to whatever was stored in the model config at registration.
410
+ base_url = get_api_endpoint_for_host(host)
411
+ if base_url == COPILOT_AUTH_CONFIG["api_base_url"]:
412
+ config_url = model_config.get("custom_endpoint", {}).get("url")
413
+ if config_url:
414
+ base_url = config_url
415
+
416
+ # Use a placeholder API key — the actual token is injected by _CopilotAuth
417
+ provider = OpenAIProvider(
418
+ api_key="copilot-session-managed",
419
+ base_url=base_url,
420
+ http_client=client,
421
+ )
422
+
423
+ # Profile telling pydantic-ai how to handle thinking: Copilot Claude models return
424
+ # it in custom fields "reasoning_text" / encrypted "reasoning_opaque".
425
+ profile = None
426
+ underlying_name = model_config.get("name", "").lower()
427
+ if underlying_name.startswith("claude-"):
428
+ from pydantic_ai.profiles.openai import OpenAIModelProfile
429
+
430
+ from .reasoning_client import patch_client_for_reasoning_opaque
431
+
432
+ # Field-mode so thinking persists across tool calls; the reasoning_opaque
433
+ # interceptor (patched onto the httpx client) re-injects the encrypted blob
434
+ # into subsequent requests, preventing 400s.
435
+ profile = OpenAIModelProfile(
436
+ openai_chat_thinking_field="reasoning_text",
437
+ openai_supports_reasoning=True,
438
+ openai_chat_send_back_thinking_parts="field",
439
+ )
440
+ patch_client_for_reasoning_opaque(client, thinking_field="reasoning_text")
441
+
442
+ return OpenAIChatModel(
443
+ model_name=model_config["name"],
444
+ provider=provider,
445
+ profile=profile,
446
+ )
447
+
448
+
449
+ def _register_model_types() -> List[Dict[str, Any]]:
450
+ """Register the ``copilot`` model type handler."""
451
+ return [{"type": "copilot", "handler": _create_copilot_model}]
452
+
453
+
454
+ # ---------------------------------------------------------------------------
455
+ # Hook registrations — executed at module import time
456
+ # ---------------------------------------------------------------------------
457
+
458
+ register_callback("custom_command_help", _custom_help)
459
+ register_callback("custom_command", _handle_custom_command)
460
+ register_callback("register_model_type", _register_model_types)