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.
- code_puppy_core_plugins/__init__.py +5 -0
- code_puppy_core_plugins/acp/README.md +266 -0
- code_puppy_core_plugins/acp/__init__.py +8 -0
- code_puppy_core_plugins/acp/agent.py +494 -0
- code_puppy_core_plugins/acp/bridge.py +309 -0
- code_puppy_core_plugins/acp/capabilities.py +73 -0
- code_puppy_core_plugins/acp/commands.py +116 -0
- code_puppy_core_plugins/acp/content.py +115 -0
- code_puppy_core_plugins/acp/io_delegation.py +231 -0
- code_puppy_core_plugins/acp/mcp_config.py +66 -0
- code_puppy_core_plugins/acp/permissions.py +159 -0
- code_puppy_core_plugins/acp/persistence.py +197 -0
- code_puppy_core_plugins/acp/register_callbacks.py +110 -0
- code_puppy_core_plugins/acp/replay.py +114 -0
- code_puppy_core_plugins/acp/session.py +329 -0
- code_puppy_core_plugins/acp/session_config.py +179 -0
- code_puppy_core_plugins/acp/state.py +135 -0
- code_puppy_core_plugins/agent_skills/__init__.py +22 -0
- code_puppy_core_plugins/agent_skills/config.py +208 -0
- code_puppy_core_plugins/agent_skills/discovery.py +337 -0
- code_puppy_core_plugins/agent_skills/downloader.py +392 -0
- code_puppy_core_plugins/agent_skills/enabled_skills.py +82 -0
- code_puppy_core_plugins/agent_skills/installer.py +22 -0
- code_puppy_core_plugins/agent_skills/metadata.py +219 -0
- code_puppy_core_plugins/agent_skills/prompt_builder.py +49 -0
- code_puppy_core_plugins/agent_skills/provider.py +52 -0
- code_puppy_core_plugins/agent_skills/register_callbacks.py +309 -0
- code_puppy_core_plugins/agent_skills/remote_catalog.py +322 -0
- code_puppy_core_plugins/agent_skills/skill_catalog.py +257 -0
- code_puppy_core_plugins/agent_skills/skill_commands.py +102 -0
- code_puppy_core_plugins/agent_skills/skills_install_menu.py +698 -0
- code_puppy_core_plugins/agent_skills/skills_menu.py +794 -0
- code_puppy_core_plugins/aws_bedrock/__init__.py +14 -0
- code_puppy_core_plugins/aws_bedrock/config.py +101 -0
- code_puppy_core_plugins/aws_bedrock/register_callbacks.py +243 -0
- code_puppy_core_plugins/aws_bedrock/utils.py +186 -0
- code_puppy_core_plugins/azure_foundry/README.md +238 -0
- code_puppy_core_plugins/azure_foundry/__init__.py +15 -0
- code_puppy_core_plugins/azure_foundry/config.py +126 -0
- code_puppy_core_plugins/azure_foundry/discovery.py +189 -0
- code_puppy_core_plugins/azure_foundry/register_callbacks.py +506 -0
- code_puppy_core_plugins/azure_foundry/token.py +182 -0
- code_puppy_core_plugins/azure_foundry/utils.py +375 -0
- code_puppy_core_plugins/btw/__init__.py +1 -0
- code_puppy_core_plugins/btw/inline_view.py +135 -0
- code_puppy_core_plugins/btw/register_callbacks.py +106 -0
- code_puppy_core_plugins/btw/side_query.py +91 -0
- code_puppy_core_plugins/chatgpt_oauth/IMAGEGEN_SKILL.md +83 -0
- code_puppy_core_plugins/chatgpt_oauth/__init__.py +8 -0
- code_puppy_core_plugins/chatgpt_oauth/config.py +52 -0
- code_puppy_core_plugins/chatgpt_oauth/image_generation.py +253 -0
- code_puppy_core_plugins/chatgpt_oauth/image_tool.py +70 -0
- code_puppy_core_plugins/chatgpt_oauth/oauth_flow.py +461 -0
- code_puppy_core_plugins/chatgpt_oauth/register_callbacks.py +288 -0
- code_puppy_core_plugins/chatgpt_oauth/test_plugin.py +663 -0
- code_puppy_core_plugins/chatgpt_oauth/usage.py +113 -0
- code_puppy_core_plugins/chatgpt_oauth/utils.py +534 -0
- code_puppy_core_plugins/claude_code_hooks/__init__.py +1 -0
- code_puppy_core_plugins/claude_code_hooks/config.py +137 -0
- code_puppy_core_plugins/claude_code_hooks/register_callbacks.py +383 -0
- code_puppy_core_plugins/claude_code_oauth/README.md +167 -0
- code_puppy_core_plugins/claude_code_oauth/SETUP.md +93 -0
- code_puppy_core_plugins/claude_code_oauth/__init__.py +25 -0
- code_puppy_core_plugins/claude_code_oauth/config.py +59 -0
- code_puppy_core_plugins/claude_code_oauth/fast_mode.py +122 -0
- code_puppy_core_plugins/claude_code_oauth/prompt_handler.py +64 -0
- code_puppy_core_plugins/claude_code_oauth/register_callbacks.py +719 -0
- code_puppy_core_plugins/claude_code_oauth/test_plugin.py +285 -0
- code_puppy_core_plugins/claude_code_oauth/token_refresh_heartbeat.py +240 -0
- code_puppy_core_plugins/claude_code_oauth/utils.py +663 -0
- code_puppy_core_plugins/code_puppy_agent/AGENTS_AND_TOOLS.md +155 -0
- code_puppy_core_plugins/code_puppy_agent/MODELS_AND_MCP.md +104 -0
- code_puppy_core_plugins/code_puppy_agent/PLUGINS_AND_CALLBACKS.md +147 -0
- code_puppy_core_plugins/code_puppy_agent/SESSIONS_AND_HISTORY.md +39 -0
- code_puppy_core_plugins/code_puppy_agent/SKILL.md +180 -0
- code_puppy_core_plugins/code_puppy_agent/SKILLS_SYSTEM.md +136 -0
- code_puppy_core_plugins/code_puppy_agent/SYSTEM_PROMPT_CONFIG_AND_I18N.md +160 -0
- code_puppy_core_plugins/code_puppy_agent/__init__.py +5 -0
- code_puppy_core_plugins/code_puppy_agent/register_callbacks.py +46 -0
- code_puppy_core_plugins/computer_use/NativeCapture.swift +123 -0
- code_puppy_core_plugins/computer_use/README.md +109 -0
- code_puppy_core_plugins/computer_use/__init__.py +1 -0
- code_puppy_core_plugins/computer_use/accessibility.py +163 -0
- code_puppy_core_plugins/computer_use/activation.py +75 -0
- code_puppy_core_plugins/computer_use/backend.py +584 -0
- code_puppy_core_plugins/computer_use/backend_types.py +5 -0
- code_puppy_core_plugins/computer_use/capture.py +110 -0
- code_puppy_core_plugins/computer_use/commands.py +62 -0
- code_puppy_core_plugins/computer_use/geometry.py +81 -0
- code_puppy_core_plugins/computer_use/inline_image.py +56 -0
- code_puppy_core_plugins/computer_use/keycodes.py +47 -0
- code_puppy_core_plugins/computer_use/policy.py +144 -0
- code_puppy_core_plugins/computer_use/register_callbacks.py +96 -0
- code_puppy_core_plugins/computer_use/safety.py +18 -0
- code_puppy_core_plugins/computer_use/settle.py +64 -0
- code_puppy_core_plugins/computer_use/state.py +86 -0
- code_puppy_core_plugins/computer_use/tools.py +469 -0
- code_puppy_core_plugins/context_indicator/__init__.py +14 -0
- code_puppy_core_plugins/context_indicator/register_callbacks.py +249 -0
- code_puppy_core_plugins/context_indicator/usage.py +40 -0
- code_puppy_core_plugins/copilot_auth/__init__.py +11 -0
- code_puppy_core_plugins/copilot_auth/config.py +93 -0
- code_puppy_core_plugins/copilot_auth/reasoning_client.py +409 -0
- code_puppy_core_plugins/copilot_auth/register_callbacks.py +460 -0
- code_puppy_core_plugins/copilot_auth/utils.py +587 -0
- code_puppy_core_plugins/customizable_commands/__init__.py +0 -0
- code_puppy_core_plugins/customizable_commands/register_callbacks.py +464 -0
- code_puppy_core_plugins/dbos_durable_exec/__init__.py +1 -0
- code_puppy_core_plugins/dbos_durable_exec/cancel.py +15 -0
- code_puppy_core_plugins/dbos_durable_exec/commands.py +31 -0
- code_puppy_core_plugins/dbos_durable_exec/config.py +31 -0
- code_puppy_core_plugins/dbos_durable_exec/lifecycle.py +83 -0
- code_puppy_core_plugins/dbos_durable_exec/register_callbacks.py +45 -0
- code_puppy_core_plugins/dbos_durable_exec/runtime.py +65 -0
- code_puppy_core_plugins/dbos_durable_exec/startup_lock.py +155 -0
- code_puppy_core_plugins/dbos_durable_exec/workflow_ids.py +16 -0
- code_puppy_core_plugins/dbos_durable_exec/wrapper.py +58 -0
- code_puppy_core_plugins/destructive_command_guard/AGENTS.md +79 -0
- code_puppy_core_plugins/destructive_command_guard/__init__.py +14 -0
- code_puppy_core_plugins/destructive_command_guard/detector.py +374 -0
- code_puppy_core_plugins/destructive_command_guard/register_callbacks.py +165 -0
- code_puppy_core_plugins/emoji_filter/__init__.py +12 -0
- code_puppy_core_plugins/emoji_filter/config.py +26 -0
- code_puppy_core_plugins/emoji_filter/register_callbacks.py +238 -0
- code_puppy_core_plugins/emoji_filter/stripper.py +45 -0
- code_puppy_core_plugins/empty_html_comment_filter/register_callbacks.py +116 -0
- code_puppy_core_plugins/example_custom_command/README.md +328 -0
- code_puppy_core_plugins/example_custom_command/register_callbacks.py +66 -0
- code_puppy_core_plugins/file_permission_handler/__init__.py +4 -0
- code_puppy_core_plugins/file_permission_handler/register_callbacks.py +575 -0
- code_puppy_core_plugins/flux_bootstrap/__init__.py +5 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/_docs/README.md +173 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/_docs/cheatsheet.md +86 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/_docs/pipeline.md +167 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/_docs/synopsis.md +392 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/about.md +51 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/address-feedback.md +129 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/ask.md +211 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/aug.md +181 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/auto-pilot.md +71 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/cheatsheet.md +16 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/commit.md +103 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/config.md +108 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/create-pr.md +195 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/exec.md +221 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/new.md +151 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/qa.md +208 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/rebase.md +180 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/review.md +304 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/split.md +120 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/squash-commits.md +179 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/status.md +46 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/tests.md +155 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/scripts/flux_about.py +154 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/scripts/flux_cheatsheet.py +248 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/scripts/flux_status.py +345 -0
- code_puppy_core_plugins/flux_bootstrap/installer.py +256 -0
- code_puppy_core_plugins/flux_bootstrap/register_callbacks.py +71 -0
- code_puppy_core_plugins/force_push_guard/__init__.py +5 -0
- code_puppy_core_plugins/force_push_guard/detector.py +96 -0
- code_puppy_core_plugins/force_push_guard/register_callbacks.py +161 -0
- code_puppy_core_plugins/fork/__init__.py +7 -0
- code_puppy_core_plugins/fork/register_callbacks.py +445 -0
- code_puppy_core_plugins/frontend_emitter/__init__.py +25 -0
- code_puppy_core_plugins/frontend_emitter/emitter.py +249 -0
- code_puppy_core_plugins/frontend_emitter/register_callbacks.py +412 -0
- code_puppy_core_plugins/frontend_emitter/session_context.py +50 -0
- code_puppy_core_plugins/grok_oauth/__init__.py +6 -0
- code_puppy_core_plugins/grok_oauth/config.py +49 -0
- code_puppy_core_plugins/grok_oauth/oauth_flow.py +213 -0
- code_puppy_core_plugins/grok_oauth/register_callbacks.py +132 -0
- code_puppy_core_plugins/grok_oauth/utils.py +195 -0
- code_puppy_core_plugins/herdr/README.md +168 -0
- code_puppy_core_plugins/herdr/__init__.py +9 -0
- code_puppy_core_plugins/herdr/client.py +339 -0
- code_puppy_core_plugins/herdr/register_callbacks.py +140 -0
- code_puppy_core_plugins/herdr/reporter.py +212 -0
- code_puppy_core_plugins/herdr/smoke.py +143 -0
- code_puppy_core_plugins/herdr/sources.py +133 -0
- code_puppy_core_plugins/hook_creator/__init__.py +1 -0
- code_puppy_core_plugins/hook_creator/register_callbacks.py +33 -0
- code_puppy_core_plugins/hook_manager/__init__.py +1 -0
- code_puppy_core_plugins/hook_manager/config.py +290 -0
- code_puppy_core_plugins/hook_manager/hooks_menu.py +571 -0
- code_puppy_core_plugins/hook_manager/register_callbacks.py +227 -0
- code_puppy_core_plugins/meta_oauth/__init__.py +1 -0
- code_puppy_core_plugins/meta_oauth/config.py +55 -0
- code_puppy_core_plugins/meta_oauth/oauth_flow.py +109 -0
- code_puppy_core_plugins/meta_oauth/register_callbacks.py +154 -0
- code_puppy_core_plugins/meta_oauth/utils.py +252 -0
- code_puppy_core_plugins/namespace_skill_search/README.md +118 -0
- code_puppy_core_plugins/namespace_skill_search/__init__.py +15 -0
- code_puppy_core_plugins/namespace_skill_search/namespaces.py +125 -0
- code_puppy_core_plugins/namespace_skill_search/register_callbacks.py +99 -0
- code_puppy_core_plugins/namespace_skill_search/search_tool.py +158 -0
- code_puppy_core_plugins/no_tools/__init__.py +0 -0
- code_puppy_core_plugins/no_tools/register_callbacks.py +42 -0
- code_puppy_core_plugins/oauth_pasteback.py +110 -0
- code_puppy_core_plugins/oauth_puppy_html.py +194 -0
- code_puppy_core_plugins/obsidian_agent/README.md +52 -0
- code_puppy_core_plugins/obsidian_agent/__init__.py +8 -0
- code_puppy_core_plugins/obsidian_agent/agent_obsidian.py +147 -0
- code_puppy_core_plugins/obsidian_agent/register_callbacks.py +13 -0
- code_puppy_core_plugins/ollama/__init__.py +1 -0
- code_puppy_core_plugins/ollama/register_callbacks.py +127 -0
- code_puppy_core_plugins/ollama_setup/__init__.py +5 -0
- code_puppy_core_plugins/ollama_setup/completer.py +38 -0
- code_puppy_core_plugins/ollama_setup/register_callbacks.py +419 -0
- code_puppy_core_plugins/plugin_list/__init__.py +0 -0
- code_puppy_core_plugins/plugin_list/plugin_contributions.py +348 -0
- code_puppy_core_plugins/plugin_list/plugin_meta.py +67 -0
- code_puppy_core_plugins/plugin_list/plugin_text_utils.py +173 -0
- code_puppy_core_plugins/plugin_list/plugins_menu.py +455 -0
- code_puppy_core_plugins/plugin_list/plugins_menu_layout.py +194 -0
- code_puppy_core_plugins/plugin_list/plugins_menu_render.py +431 -0
- code_puppy_core_plugins/plugin_list/project_trust_flow.py +162 -0
- code_puppy_core_plugins/plugin_list/register_callbacks.py +281 -0
- code_puppy_core_plugins/pop_command/__init__.py +1 -0
- code_puppy_core_plugins/pop_command/register_callbacks.py +191 -0
- code_puppy_core_plugins/prompt_newline/__init__.py +13 -0
- code_puppy_core_plugins/prompt_newline/config.py +21 -0
- code_puppy_core_plugins/prompt_newline/register_callbacks.py +163 -0
- code_puppy_core_plugins/prune/__init__.py +1 -0
- code_puppy_core_plugins/prune/prune_menu.py +308 -0
- code_puppy_core_plugins/prune/prune_model.py +517 -0
- code_puppy_core_plugins/prune/prune_render.py +354 -0
- code_puppy_core_plugins/prune/register_callbacks.py +388 -0
- code_puppy_core_plugins/puppy_kennel/README.md +203 -0
- code_puppy_core_plugins/puppy_kennel/__init__.py +6 -0
- code_puppy_core_plugins/puppy_kennel/commands.py +206 -0
- code_puppy_core_plugins/puppy_kennel/config.py +36 -0
- code_puppy_core_plugins/puppy_kennel/kennel.py +368 -0
- code_puppy_core_plugins/puppy_kennel/packer.py +152 -0
- code_puppy_core_plugins/puppy_kennel/recorder.py +83 -0
- code_puppy_core_plugins/puppy_kennel/register_callbacks.py +109 -0
- code_puppy_core_plugins/puppy_kennel/retriever.py +28 -0
- code_puppy_core_plugins/puppy_kennel/schema.py +78 -0
- code_puppy_core_plugins/puppy_kennel/state.py +68 -0
- code_puppy_core_plugins/puppy_kennel/tools.py +449 -0
- code_puppy_core_plugins/puppy_kennel/wings.py +110 -0
- code_puppy_core_plugins/puppy_spinner/README.md +93 -0
- code_puppy_core_plugins/puppy_spinner/__init__.py +11 -0
- code_puppy_core_plugins/puppy_spinner/builtin_frames.py +172 -0
- code_puppy_core_plugins/puppy_spinner/commands.py +116 -0
- code_puppy_core_plugins/puppy_spinner/picker.py +379 -0
- code_puppy_core_plugins/puppy_spinner/register_callbacks.py +193 -0
- code_puppy_core_plugins/puppy_spinner/spinners.py +444 -0
- code_puppy_core_plugins/quick_resume/__init__.py +0 -0
- code_puppy_core_plugins/quick_resume/register_callbacks.py +77 -0
- code_puppy_core_plugins/review_pr/__init__.py +1 -0
- code_puppy_core_plugins/review_pr/register_callbacks.py +162 -0
- code_puppy_core_plugins/shell_safety/__init__.py +6 -0
- code_puppy_core_plugins/shell_safety/agent_shell_safety.py +69 -0
- code_puppy_core_plugins/shell_safety/command_cache.py +156 -0
- code_puppy_core_plugins/shell_safety/register_callbacks.py +203 -0
- code_puppy_core_plugins/stack_dump/__init__.py +1 -0
- code_puppy_core_plugins/stack_dump/register_callbacks.py +79 -0
- code_puppy_core_plugins/statusline/__init__.py +14 -0
- code_puppy_core_plugins/statusline/config.py +68 -0
- code_puppy_core_plugins/statusline/payload.py +138 -0
- code_puppy_core_plugins/statusline/prompt_patch.py +76 -0
- code_puppy_core_plugins/statusline/register_callbacks.py +45 -0
- code_puppy_core_plugins/statusline/runner.py +122 -0
- code_puppy_core_plugins/statusline/statusline_command.py +197 -0
- code_puppy_core_plugins/steer_queue/__init__.py +10 -0
- code_puppy_core_plugins/steer_queue/queue_menu.py +444 -0
- code_puppy_core_plugins/steer_queue/register_callbacks.py +138 -0
- code_puppy_core_plugins/subagent_panel/README.md +102 -0
- code_puppy_core_plugins/subagent_panel/__init__.py +24 -0
- code_puppy_core_plugins/subagent_panel/coalesce_patch.py +242 -0
- code_puppy_core_plugins/subagent_panel/panel_render.py +145 -0
- code_puppy_core_plugins/subagent_panel/register_callbacks.py +535 -0
- code_puppy_core_plugins/subagent_panel/resume_repaint.py +112 -0
- code_puppy_core_plugins/subagent_panel/state.py +231 -0
- code_puppy_core_plugins/switch_agent_resume/__init__.py +5 -0
- code_puppy_core_plugins/switch_agent_resume/register_callbacks.py +314 -0
- code_puppy_core_plugins/theme/README.md +86 -0
- code_puppy_core_plugins/theme/__init__.py +14 -0
- code_puppy_core_plugins/theme/bundled_palettes.py +346 -0
- code_puppy_core_plugins/theme/content_styles.py +146 -0
- code_puppy_core_plugins/theme/osc_palette.py +178 -0
- code_puppy_core_plugins/theme/picker.py +358 -0
- code_puppy_core_plugins/theme/prompt_toolkit_theme.py +113 -0
- code_puppy_core_plugins/theme/register_callbacks.py +348 -0
- code_puppy_core_plugins/theme/rich_themes.py +202 -0
- code_puppy_core_plugins/theme/themes.py +720 -0
- code_puppy_core_plugins/timestamp_heartbeat/__init__.py +1 -0
- code_puppy_core_plugins/timestamp_heartbeat/register_callbacks.py +114 -0
- code_puppy_core_plugins/token_ratio_learner/__init__.py +5 -0
- code_puppy_core_plugins/token_ratio_learner/ratios.py +208 -0
- code_puppy_core_plugins/token_ratio_learner/register_callbacks.py +213 -0
- code_puppy_core_plugins/universal_constructor/__init__.py +13 -0
- code_puppy_core_plugins/universal_constructor/models.py +138 -0
- code_puppy_core_plugins/universal_constructor/provider.py +62 -0
- code_puppy_core_plugins/universal_constructor/register_callbacks.py +75 -0
- code_puppy_core_plugins/universal_constructor/registry.py +302 -0
- code_puppy_core_plugins/universal_constructor/sandbox.py +584 -0
- code_puppy_core_plugins/wide_completion_menu/__init__.py +6 -0
- code_puppy_core_plugins/wide_completion_menu/register_callbacks.py +165 -0
- code_puppy_core_plugins/wiggum/__init__.py +1 -0
- code_puppy_core_plugins/wiggum/goal_runs.py +91 -0
- code_puppy_core_plugins/wiggum/judge.py +299 -0
- code_puppy_core_plugins/wiggum/judge_config.py +249 -0
- code_puppy_core_plugins/wiggum/judges_menu.py +814 -0
- code_puppy_core_plugins/wiggum/register_callbacks.py +569 -0
- code_puppy_core_plugins/wiggum/state.py +89 -0
- code_puppy_core_plugins/yolo_cli/__init__.py +1 -0
- code_puppy_core_plugins/yolo_cli/register_callbacks.py +41 -0
- code_puppy_core_plugins-0.0.2.dist-info/METADATA +64 -0
- code_puppy_core_plugins-0.0.2.dist-info/RECORD +313 -0
- code_puppy_core_plugins-0.0.2.dist-info/WHEEL +4 -0
- code_puppy_core_plugins-0.0.2.dist-info/entry_points.txt +55 -0
- code_puppy_core_plugins-0.0.2.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"""Pattern detection for git force push commands.
|
|
2
|
+
|
|
3
|
+
Detects force push patterns in shell commands, covering all the sneaky
|
|
4
|
+
ways git lets you wreck a remote branch.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import re
|
|
8
|
+
from dataclasses import dataclass
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass
|
|
12
|
+
class ForcePushMatch:
|
|
13
|
+
"""Result of a force push pattern match."""
|
|
14
|
+
|
|
15
|
+
pattern_name: str
|
|
16
|
+
description: str
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
# Matches shell operators that precede a new command in a pipeline/chain.
|
|
20
|
+
# E.g. "cd foo && git push --force" or "true || git push -f"
|
|
21
|
+
_SHELL_OPERATOR_RE = re.compile(r"(?:^|&&|\|\||;|\|)\s*git\s+push\b", re.MULTILINE)
|
|
22
|
+
|
|
23
|
+
# Ordered by specificity — first match wins.
|
|
24
|
+
# Each tuple: (compiled regex, human-readable name, what it catches)
|
|
25
|
+
_FORCE_PUSH_PATTERNS: list[tuple[re.Pattern, str, str]] = [
|
|
26
|
+
(
|
|
27
|
+
re.compile(r"\bgit\s+push\b.*--force-with-lease"),
|
|
28
|
+
"--force-with-lease",
|
|
29
|
+
"force push with lease (safer, but still rewrites history)",
|
|
30
|
+
),
|
|
31
|
+
(
|
|
32
|
+
re.compile(r"\bgit\s+push\b.*--force-if-includes"),
|
|
33
|
+
"--force-if-includes",
|
|
34
|
+
"force push with includes check (still rewrites history)",
|
|
35
|
+
),
|
|
36
|
+
(
|
|
37
|
+
re.compile(r"\bgit\s+push\b.*--force"),
|
|
38
|
+
"--force",
|
|
39
|
+
"force push (rewrites remote history)",
|
|
40
|
+
),
|
|
41
|
+
(
|
|
42
|
+
re.compile(r"\bgit\s+push\b.*\s-f\b"),
|
|
43
|
+
"-f",
|
|
44
|
+
"force push shorthand (rewrites remote history)",
|
|
45
|
+
),
|
|
46
|
+
(
|
|
47
|
+
re.compile(r"\bgit\s+push\b.*\s-F\b"),
|
|
48
|
+
"-F",
|
|
49
|
+
"force push shorthand (rewrites remote history)",
|
|
50
|
+
),
|
|
51
|
+
# The +refspec syntax: git push origin +main, git push origin +HEAD:main
|
|
52
|
+
(
|
|
53
|
+
re.compile(r"\bgit\s+push\b.*\s\+"),
|
|
54
|
+
"+refspec",
|
|
55
|
+
"force push via +refspec prefix (rewrites remote history)",
|
|
56
|
+
),
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _is_git_push_a_command(command: str) -> bool:
|
|
61
|
+
"""Check that 'git push' is an actual command, not a string argument.
|
|
62
|
+
|
|
63
|
+
Handles compound commands like "cd foo && git push --force" while
|
|
64
|
+
avoiding false positives like "echo 'git push --force'".
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
command: The shell command string to inspect.
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
True if 'git push' appears as an actual command invocation.
|
|
71
|
+
"""
|
|
72
|
+
return bool(_SHELL_OPERATOR_RE.search(command))
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def detect_force_push(command: str) -> ForcePushMatch | None:
|
|
76
|
+
"""Check if a shell command contains a git force push.
|
|
77
|
+
|
|
78
|
+
Args:
|
|
79
|
+
command: The shell command string to inspect.
|
|
80
|
+
|
|
81
|
+
Returns:
|
|
82
|
+
ForcePushMatch if a force push pattern is found, None otherwise.
|
|
83
|
+
"""
|
|
84
|
+
# Quick pre-filter: skip entirely if "push" isn't even in the command
|
|
85
|
+
if "push" not in command:
|
|
86
|
+
return None
|
|
87
|
+
|
|
88
|
+
# Ensure 'git push' is an actual command, not a string argument
|
|
89
|
+
if not _is_git_push_a_command(command):
|
|
90
|
+
return None
|
|
91
|
+
|
|
92
|
+
for pattern, name, description in _FORCE_PUSH_PATTERNS:
|
|
93
|
+
if pattern.search(command):
|
|
94
|
+
return ForcePushMatch(pattern_name=name, description=description)
|
|
95
|
+
|
|
96
|
+
return None
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
"""Callback registration for the force push guard plugin.
|
|
2
|
+
|
|
3
|
+
Hooks into the run_shell_command phase to intercept git force push
|
|
4
|
+
commands and prompt the user for approval before allowing them through.
|
|
5
|
+
Returns {"blocked": True} to deny, None to allow.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import sys
|
|
9
|
+
from typing import Any, Dict, Optional
|
|
10
|
+
|
|
11
|
+
from rich.text import Text
|
|
12
|
+
|
|
13
|
+
from code_puppy.callbacks import register_callback
|
|
14
|
+
from code_puppy.config import (
|
|
15
|
+
get_disable_dangerous_command_guard,
|
|
16
|
+
is_dangerous_command_allowlisted,
|
|
17
|
+
)
|
|
18
|
+
from code_puppy.messaging import emit_info, emit_warning
|
|
19
|
+
from code_puppy_core_plugins.force_push_guard.detector import detect_force_push
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _is_interactive() -> bool:
|
|
23
|
+
"""Check if we're in an interactive terminal that can show prompts."""
|
|
24
|
+
try:
|
|
25
|
+
return sys.stdin.isatty()
|
|
26
|
+
except (AttributeError, OSError):
|
|
27
|
+
return False
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
async def force_push_guard_callback(
|
|
31
|
+
context: Any, command: str, cwd: Optional[str] = None, timeout: int = 60
|
|
32
|
+
) -> Optional[Dict[str, Any]]:
|
|
33
|
+
"""Intercept shell commands containing git force push operations.
|
|
34
|
+
|
|
35
|
+
When a force push is detected:
|
|
36
|
+
- Interactive TTY: prompt the user with approve/reject options.
|
|
37
|
+
- Non-interactive (CI, sub-agent, piped): hard-block with an error.
|
|
38
|
+
|
|
39
|
+
This runs on *every* shell command, but the heavy lifting (regex
|
|
40
|
+
matching) is gated behind a cheap "push" substring check inside
|
|
41
|
+
detect_force_push().
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
context: Execution context (unused).
|
|
45
|
+
command: The shell command about to run.
|
|
46
|
+
cwd: Working directory (unused).
|
|
47
|
+
timeout: Command timeout (unused).
|
|
48
|
+
|
|
49
|
+
Returns:
|
|
50
|
+
None if the command is safe to proceed or user approved it.
|
|
51
|
+
Dict with blocked=True if a force push was detected and rejected.
|
|
52
|
+
"""
|
|
53
|
+
# Check if dangerous command guards are disabled
|
|
54
|
+
if get_disable_dangerous_command_guard():
|
|
55
|
+
return None
|
|
56
|
+
|
|
57
|
+
match = detect_force_push(command)
|
|
58
|
+
if match is None:
|
|
59
|
+
return None
|
|
60
|
+
|
|
61
|
+
# Granular allowlist: trusted force-push patterns bypass the guard while
|
|
62
|
+
# everything else stays protected (unlike the all-or-nothing disable flag).
|
|
63
|
+
if is_dangerous_command_allowlisted(match.pattern_name):
|
|
64
|
+
emit_info(
|
|
65
|
+
f"Allowlisted force-push pattern '{match.pattern_name}' -- "
|
|
66
|
+
"proceeding (guard still active for other patterns)."
|
|
67
|
+
)
|
|
68
|
+
return None
|
|
69
|
+
|
|
70
|
+
# --- Interactive TTY: ask the user ---
|
|
71
|
+
if _is_interactive():
|
|
72
|
+
return await _prompt_user_approval(command, match)
|
|
73
|
+
|
|
74
|
+
# --- Non-interactive: hard-block ---
|
|
75
|
+
return _block_command(command, match)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
async def _prompt_user_approval(command: str, match: Any) -> Optional[Dict[str, Any]]:
|
|
79
|
+
"""Show an interactive approval prompt for the detected force push.
|
|
80
|
+
|
|
81
|
+
Args:
|
|
82
|
+
command: The original shell command.
|
|
83
|
+
match: The ForcePushMatch from the detector.
|
|
84
|
+
|
|
85
|
+
Returns:
|
|
86
|
+
None if user approves, Dict with blocked=True if rejected.
|
|
87
|
+
"""
|
|
88
|
+
from code_puppy.tools.common import get_user_approval_async
|
|
89
|
+
|
|
90
|
+
panel_content = Text()
|
|
91
|
+
panel_content.append("⚠️ Force push detected: ", style="bold yellow")
|
|
92
|
+
panel_content.append(match.pattern_name, style="bold red")
|
|
93
|
+
panel_content.append("\n", style="")
|
|
94
|
+
panel_content.append(f" {match.description}", style="dim")
|
|
95
|
+
panel_content.append("\n\n", style="")
|
|
96
|
+
panel_content.append("$ ", style="bold green")
|
|
97
|
+
panel_content.append(command, style="bold white")
|
|
98
|
+
panel_content.append(
|
|
99
|
+
"\n\nForce pushing rewrites remote history and can destroy others' work.",
|
|
100
|
+
style="yellow",
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
confirmed, user_feedback = await get_user_approval_async(
|
|
104
|
+
title="Force Push Guard 🛡️",
|
|
105
|
+
content=panel_content,
|
|
106
|
+
border_style="red",
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
if confirmed:
|
|
110
|
+
emit_info("⚠️ Force push approved — proceeding with caution.")
|
|
111
|
+
return None # Allow the command through
|
|
112
|
+
|
|
113
|
+
# Rejected
|
|
114
|
+
reason = user_feedback or "User rejected force push"
|
|
115
|
+
return {
|
|
116
|
+
"blocked": True,
|
|
117
|
+
"reasoning": f"Force push rejected: {match.pattern_name} — {reason}",
|
|
118
|
+
"error_message": (
|
|
119
|
+
f"🛑 Force push rejected. Detected {match.pattern_name} "
|
|
120
|
+
f"in command:\n {command}\n"
|
|
121
|
+
f" {match.description}\n"
|
|
122
|
+
f"Feedback: {reason}"
|
|
123
|
+
),
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def _block_command(command: str, match: Any) -> Dict[str, Any]:
|
|
128
|
+
"""Hard-block a force push in non-interactive contexts.
|
|
129
|
+
|
|
130
|
+
Args:
|
|
131
|
+
command: The original shell command.
|
|
132
|
+
match: The ForcePushMatch from the detector.
|
|
133
|
+
|
|
134
|
+
Returns:
|
|
135
|
+
Dict with blocked=True and a descriptive error.
|
|
136
|
+
"""
|
|
137
|
+
error_message = (
|
|
138
|
+
f"🛑 Force push blocked! Detected {match.pattern_name} "
|
|
139
|
+
f"in command:\n {command}\n"
|
|
140
|
+
f" {match.description}\n\n"
|
|
141
|
+
f"Force pushing rewrites remote history and can destroy others' work.\n"
|
|
142
|
+
f"If you *really* need to force push, use the exact command directly\n"
|
|
143
|
+
f"in your terminal (outside code puppy) after double-checking the target branch."
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
emit_warning(error_message)
|
|
147
|
+
|
|
148
|
+
return {
|
|
149
|
+
"blocked": True,
|
|
150
|
+
"reasoning": f"Force push detected: {match.pattern_name} — {match.description}",
|
|
151
|
+
"error_message": error_message,
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def register() -> None:
|
|
156
|
+
"""Register the force push guard callback."""
|
|
157
|
+
register_callback("run_shell_command", force_push_guard_callback)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
# Auto-register when this module is imported
|
|
161
|
+
register()
|