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,65 @@
|
|
|
1
|
+
"""Async context manager wrapping pydantic_agent.run() with DBOS workflow ID
|
|
2
|
+
and (when needed) MCP toolset injection on the inner pydantic agent."""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
from contextlib import asynccontextmanager
|
|
7
|
+
|
|
8
|
+
from .workflow_ids import generate_dbos_workflow_id
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def skip_fallback_render(_agent) -> bool:
|
|
12
|
+
"""DBOS renders its own output; tell core to skip the non-streaming fallback.
|
|
13
|
+
|
|
14
|
+
Only valid when DBOS is actually launched — otherwise we'd skip the
|
|
15
|
+
fallback render for plain pydantic agents, leaving users with no output.
|
|
16
|
+
"""
|
|
17
|
+
from .lifecycle import is_launched
|
|
18
|
+
|
|
19
|
+
return is_launched()
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@asynccontextmanager
|
|
23
|
+
async def dbos_run_context(agent, pydantic_agent, group_id, mcp_servers):
|
|
24
|
+
"""Wrap a run() call with SetWorkflowID and a temporary MCP toolset swap.
|
|
25
|
+
|
|
26
|
+
For sub-agent invocations (group_id starting with 'invoke_agent'), append
|
|
27
|
+
an atomic counter to ensure DBOS workflow ID uniqueness across rapid
|
|
28
|
+
back-to-back calls. For the main agent, use group_id as-is.
|
|
29
|
+
"""
|
|
30
|
+
from .lifecycle import is_launched
|
|
31
|
+
|
|
32
|
+
if not is_launched():
|
|
33
|
+
# DBOS not launched (e.g. running inside pytest) — be a no-op so the
|
|
34
|
+
# plain pydantic agent run proceeds normally.
|
|
35
|
+
yield
|
|
36
|
+
return
|
|
37
|
+
|
|
38
|
+
try:
|
|
39
|
+
from dbos import SetWorkflowID
|
|
40
|
+
except ImportError:
|
|
41
|
+
yield
|
|
42
|
+
return
|
|
43
|
+
|
|
44
|
+
workflow_id = (
|
|
45
|
+
generate_dbos_workflow_id(group_id)
|
|
46
|
+
if group_id and group_id.startswith("invoke_agent")
|
|
47
|
+
else group_id
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
# The inner pydantic agent under DBOSAgent is exposed via `.wrapped`
|
|
51
|
+
# (see pydantic_ai.agent.WrapperAgent). Fall back defensively.
|
|
52
|
+
inner = getattr(pydantic_agent, "wrapped", pydantic_agent)
|
|
53
|
+
|
|
54
|
+
original = None
|
|
55
|
+
swapped = False
|
|
56
|
+
if mcp_servers:
|
|
57
|
+
original = getattr(inner, "_toolsets", []) or []
|
|
58
|
+
inner._toolsets = list(original) + list(mcp_servers)
|
|
59
|
+
swapped = True
|
|
60
|
+
try:
|
|
61
|
+
with SetWorkflowID(workflow_id):
|
|
62
|
+
yield workflow_id
|
|
63
|
+
finally:
|
|
64
|
+
if swapped:
|
|
65
|
+
inner._toolsets = original
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"""Cross-process startup serialization for the DBOS durable-exec plugin.
|
|
2
|
+
|
|
3
|
+
Multiple Code Puppy instances launched at the same instant (e.g. several
|
|
4
|
+
Zellij panes each spawning their own process) all open the *same* shared
|
|
5
|
+
DBOS SQLite system database and run schema migration + workflow recovery
|
|
6
|
+
during ``DBOS.launch()``. SQLite is single-writer, so the racers collide on
|
|
7
|
+
the write lock, and the losers either raise ``database is locked`` (or an
|
|
8
|
+
Alembic migration conflict) and disable durable execution -- or, on older
|
|
9
|
+
builds, exit the whole process with code 1.
|
|
10
|
+
|
|
11
|
+
This module provides:
|
|
12
|
+
|
|
13
|
+
* :func:`interprocess_lock` -- a cross-platform advisory file lock so that
|
|
14
|
+
DBOS initialization happens one process at a time. Late starters *wait*
|
|
15
|
+
for the lock instead of racing the migration.
|
|
16
|
+
* :func:`enable_sqlite_wal` -- flips the shared SQLite database into WAL
|
|
17
|
+
journal mode (a persistent, header-level setting) so that, once
|
|
18
|
+
initialized, concurrent reads/writes are far less likely to block.
|
|
19
|
+
|
|
20
|
+
Both helpers fail soft: locking and PRAGMA tuning are best-effort
|
|
21
|
+
optimizations, never correctness requirements, so any platform quirk
|
|
22
|
+
degrades to the previous (racy) behavior rather than blocking startup.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
from __future__ import annotations
|
|
26
|
+
|
|
27
|
+
import contextlib
|
|
28
|
+
import os
|
|
29
|
+
import sys
|
|
30
|
+
import time
|
|
31
|
+
from typing import Iterator
|
|
32
|
+
|
|
33
|
+
# Platform-specific locking primitives; deliberately no third-party dep
|
|
34
|
+
# (filelock/portalocker) — the stdlib covers both POSIX and Windows.
|
|
35
|
+
try: # POSIX
|
|
36
|
+
import fcntl
|
|
37
|
+
|
|
38
|
+
_HAVE_FCNTL = True
|
|
39
|
+
except ImportError: # pragma: no cover - Windows
|
|
40
|
+
_HAVE_FCNTL = False
|
|
41
|
+
|
|
42
|
+
try: # Windows
|
|
43
|
+
import msvcrt
|
|
44
|
+
|
|
45
|
+
_HAVE_MSVCRT = True
|
|
46
|
+
except ImportError: # pragma: no cover - POSIX
|
|
47
|
+
_HAVE_MSVCRT = False
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _try_acquire(fd: int) -> bool:
|
|
51
|
+
"""Attempt a single non-blocking exclusive lock on ``fd``.
|
|
52
|
+
|
|
53
|
+
Returns True on success, False if the lock is currently held elsewhere.
|
|
54
|
+
"""
|
|
55
|
+
if _HAVE_FCNTL:
|
|
56
|
+
try:
|
|
57
|
+
fcntl.flock(fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
|
|
58
|
+
return True
|
|
59
|
+
except OSError:
|
|
60
|
+
return False
|
|
61
|
+
if _HAVE_MSVCRT:
|
|
62
|
+
try:
|
|
63
|
+
msvcrt.locking(fd, msvcrt.LK_NBLCK, 1)
|
|
64
|
+
return True
|
|
65
|
+
except OSError:
|
|
66
|
+
return False
|
|
67
|
+
# No locking primitive available: behave as if always acquired.
|
|
68
|
+
return True
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _release(fd: int) -> None:
|
|
72
|
+
"""Best-effort release of a lock previously taken on ``fd``."""
|
|
73
|
+
try:
|
|
74
|
+
if _HAVE_FCNTL:
|
|
75
|
+
fcntl.flock(fd, fcntl.LOCK_UN)
|
|
76
|
+
elif _HAVE_MSVCRT:
|
|
77
|
+
msvcrt.locking(fd, msvcrt.LK_UNLCK, 1)
|
|
78
|
+
except OSError:
|
|
79
|
+
pass
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
@contextlib.contextmanager
|
|
83
|
+
def interprocess_lock(lock_path: str, timeout: float = 30.0) -> Iterator[bool]:
|
|
84
|
+
"""Hold a cross-process advisory lock for the duration of the block.
|
|
85
|
+
|
|
86
|
+
Serializes a critical section across separate Code Puppy processes. Late
|
|
87
|
+
arrivals poll until the holder releases or ``timeout`` seconds elapse.
|
|
88
|
+
|
|
89
|
+
Yields:
|
|
90
|
+
True if the lock was actually acquired, False if it timed out (the
|
|
91
|
+
caller still runs -- we never want a cosmetic lock to *prevent*
|
|
92
|
+
startup, only to order it when possible).
|
|
93
|
+
"""
|
|
94
|
+
os.makedirs(os.path.dirname(lock_path), exist_ok=True)
|
|
95
|
+
|
|
96
|
+
fd = None
|
|
97
|
+
acquired = False
|
|
98
|
+
try:
|
|
99
|
+
# Windows requires a real byte in the file to lock a region.
|
|
100
|
+
fd = os.open(lock_path, os.O_RDWR | os.O_CREAT, 0o644)
|
|
101
|
+
if _HAVE_MSVCRT:
|
|
102
|
+
try:
|
|
103
|
+
os.write(fd, b"\0")
|
|
104
|
+
os.lseek(fd, 0, os.SEEK_SET)
|
|
105
|
+
except OSError:
|
|
106
|
+
pass
|
|
107
|
+
|
|
108
|
+
deadline = time.monotonic() + max(timeout, 0.0)
|
|
109
|
+
while True:
|
|
110
|
+
if _try_acquire(fd):
|
|
111
|
+
acquired = True
|
|
112
|
+
break
|
|
113
|
+
if time.monotonic() >= deadline:
|
|
114
|
+
break
|
|
115
|
+
time.sleep(0.1)
|
|
116
|
+
|
|
117
|
+
yield acquired
|
|
118
|
+
finally:
|
|
119
|
+
if fd is not None:
|
|
120
|
+
if acquired:
|
|
121
|
+
_release(fd)
|
|
122
|
+
try:
|
|
123
|
+
os.close(fd)
|
|
124
|
+
except OSError:
|
|
125
|
+
pass
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def enable_sqlite_wal(sqlite_path: str) -> None:
|
|
129
|
+
"""Switch the shared SQLite DB to WAL journal mode (best effort).
|
|
130
|
+
|
|
131
|
+
WAL is a persistent, header-level setting, so a single successful call
|
|
132
|
+
sticks for every future connection (including DBOS's own engine). It lets
|
|
133
|
+
readers and a writer coexist, dramatically reducing ``database is locked``
|
|
134
|
+
errors at runtime. Failures are swallowed -- this is pure optimization.
|
|
135
|
+
"""
|
|
136
|
+
try:
|
|
137
|
+
import sqlite3
|
|
138
|
+
except ImportError: # pragma: no cover - sqlite3 is stdlib
|
|
139
|
+
return
|
|
140
|
+
|
|
141
|
+
try:
|
|
142
|
+
os.makedirs(os.path.dirname(sqlite_path), exist_ok=True)
|
|
143
|
+
# busy_timeout here only affects *this* connection, but WAL is what
|
|
144
|
+
# we actually persist. timeout keeps this probe from hanging.
|
|
145
|
+
conn = sqlite3.connect(sqlite_path, timeout=5.0)
|
|
146
|
+
try:
|
|
147
|
+
conn.execute("PRAGMA journal_mode=WAL;")
|
|
148
|
+
conn.execute("PRAGMA busy_timeout=30000;")
|
|
149
|
+
conn.commit()
|
|
150
|
+
finally:
|
|
151
|
+
conn.close()
|
|
152
|
+
except Exception as exc: # noqa: BLE001 - cosmetic optimization, fail soft
|
|
153
|
+
# Surface a hint in debug mode but never block startup.
|
|
154
|
+
if os.environ.get("CODE_PUPPY_DEBUG"):
|
|
155
|
+
sys.stderr.write(f"[dbos_durable_exec] WAL setup skipped: {exc}\n")
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""Atomic counter for unique DBOS workflow IDs (sub-agent invocations)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import itertools
|
|
6
|
+
|
|
7
|
+
_dbos_workflow_counter = itertools.count()
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def generate_dbos_workflow_id(base_id: str) -> str:
|
|
11
|
+
"""Generate a unique DBOS workflow ID by appending an atomic counter.
|
|
12
|
+
|
|
13
|
+
DBOS requires workflow IDs to be unique across all executions.
|
|
14
|
+
"""
|
|
15
|
+
counter = next(_dbos_workflow_counter)
|
|
16
|
+
return f"{base_id}-{counter}"
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""DBOSAgent wrapper, registered via the wrap_pydantic_agent hook.
|
|
2
|
+
|
|
3
|
+
The DBOS wrapper can't pickle async-generator MCP toolsets, so we stash
|
|
4
|
+
them off the inner pydantic agent before wrapping. They're restored at
|
|
5
|
+
run-time inside :mod:`runtime` so MCP tools remain available during the run.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import itertools
|
|
11
|
+
|
|
12
|
+
_reload_count = itertools.count()
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def wrap_with_dbos_agent(
|
|
16
|
+
agent,
|
|
17
|
+
pydantic_agent,
|
|
18
|
+
*,
|
|
19
|
+
event_stream_handler=None,
|
|
20
|
+
message_group=None,
|
|
21
|
+
kind: str = "main",
|
|
22
|
+
):
|
|
23
|
+
"""Return a DBOSAgent wrapping ``pydantic_agent`` (or None if DBOS missing).
|
|
24
|
+
|
|
25
|
+
Returns None — meaning "don't wrap, leave the plain pydantic agent alone" —
|
|
26
|
+
in three cases:
|
|
27
|
+
1. pydantic_ai.durable_exec.dbos is not importable.
|
|
28
|
+
2. DBOS itself was never launched (e.g. wrapper hook fired in the
|
|
29
|
+
pytest process where on_startup() was never called).
|
|
30
|
+
|
|
31
|
+
Without case 2 the wrapper would hand back a DBOSAgent whose .run()
|
|
32
|
+
fails because there is no running DBOS instance — exactly the
|
|
33
|
+
`run_with_mcp returned None` regression seen when [durable] extras
|
|
34
|
+
were installed in the CI test environment.
|
|
35
|
+
"""
|
|
36
|
+
from .lifecycle import is_launched
|
|
37
|
+
|
|
38
|
+
if not is_launched():
|
|
39
|
+
return None
|
|
40
|
+
|
|
41
|
+
try:
|
|
42
|
+
from pydantic_ai.durable_exec.dbos import DBOSAgent
|
|
43
|
+
except ImportError:
|
|
44
|
+
return None
|
|
45
|
+
|
|
46
|
+
# Reset toolsets — DBOS can't pickle async-generator MCP toolsets.
|
|
47
|
+
# The runtime hook re-injects MCP servers from its own arg at run time.
|
|
48
|
+
pydantic_agent._toolsets = []
|
|
49
|
+
|
|
50
|
+
name_suffix = next(_reload_count)
|
|
51
|
+
agent_name = getattr(agent, "name", "agent")
|
|
52
|
+
# Sub-agent path historically didn't pass an event stream handler.
|
|
53
|
+
handler = event_stream_handler if kind == "main" else None
|
|
54
|
+
return DBOSAgent(
|
|
55
|
+
pydantic_agent,
|
|
56
|
+
name=f"{agent_name}-{kind}-{name_suffix}",
|
|
57
|
+
event_stream_handler=handler,
|
|
58
|
+
)
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# AGENTS.md — Destructive Command Guard
|
|
2
|
+
|
|
3
|
+
> Scope: **this plugin only** (`code_puppy/plugins/destructive_command_guard/`).
|
|
4
|
+
> It intercepts destructive shell commands (`rm -rf /`, `git reset --hard`,
|
|
5
|
+
> `docker prune`, `diskpart`, ...) and prompts/blocks before they run.
|
|
6
|
+
> Force-push blocking is a **separate sibling plugin** (`force_push_guard/`) —
|
|
7
|
+
> out of scope here, but the two share the allowlist (see below).
|
|
8
|
+
|
|
9
|
+
## What lives here
|
|
10
|
+
|
|
11
|
+
| File | Responsibility |
|
|
12
|
+
|------|----------------|
|
|
13
|
+
| `detector.py` | Pure-regex detection. No LLM, no I/O, no config reads. Returns a `DestructiveCommandMatch(pattern_name, description)` or `None`. |
|
|
14
|
+
| `register_callbacks.py` | The `run_shell_command` hook: legacy disable flag → detect → allowlist → interactive prompt (TTY) / hard-block (non-interactive). |
|
|
15
|
+
| `__init__.py` | Docstring inventory of covered patterns. Keep it in sync when you add patterns. |
|
|
16
|
+
|
|
17
|
+
Config knobs live in `code_puppy/config.py` (NOT here):
|
|
18
|
+
- `disable_dangerous_command_guard` — legacy all-or-nothing kill-switch (also disables force-push guard). `get_disable_dangerous_command_guard()`.
|
|
19
|
+
- `dangerous_command_guard_allow` — granular per-pattern allowlist, shared with the force-push guard. `get_dangerous_command_guard_allowlist()` / `is_dangerous_command_allowlisted()`.
|
|
20
|
+
|
|
21
|
+
Tests: `tests/plugins/test_destructive_command_detector.py` (detector) and
|
|
22
|
+
`tests/plugins/test_command_guard_allowlist.py` (allowlist + callback).
|
|
23
|
+
|
|
24
|
+
## Callback precedence (do not reorder without cause)
|
|
25
|
+
|
|
26
|
+
1. `get_disable_dangerous_command_guard()` → if True, allow (full legacy bypass).
|
|
27
|
+
2. `detect_destructive_command(command)` → if `None`, allow.
|
|
28
|
+
3. `is_dangerous_command_allowlisted(match.pattern_name)` → if True, allow silently.
|
|
29
|
+
4. Interactive TTY → prompt the user (approve / reject).
|
|
30
|
+
5. Non-interactive (CI, sub-agent, piped) → **hard-block** with an error dict.
|
|
31
|
+
|
|
32
|
+
Return `None` to allow, `{"blocked": True, "reasoning": ..., "error_message": ...}` to deny.
|
|
33
|
+
|
|
34
|
+
## Recipe: add a new destructive pattern
|
|
35
|
+
|
|
36
|
+
1. **Add the regex tuple** to the right list in `detector.py`
|
|
37
|
+
(`_UNIX_DESTRUCTIVE_PATTERNS`, `_POWERSHELL_...`, or `_CMD_...`):
|
|
38
|
+
`(re.compile(r"..."), "short-name", "human description")`.
|
|
39
|
+
Order matters — **first match wins**; put more-specific patterns first.
|
|
40
|
+
2. **Add a pre-filter substring** to `_PREFILTER_SUBSTRINGS` if your keyword
|
|
41
|
+
isn't already there. Detection bails early unless a cheap substring hits,
|
|
42
|
+
so a missing prefilter = your pattern never fires.
|
|
43
|
+
3. **Add tests** in `tests/plugins/test_destructive_command_detector.py`.
|
|
44
|
+
Use the `_hits(cmd)` / `_miss(cmd)` helpers (they prefix `&& ` so
|
|
45
|
+
`_is_real_command` passes). Add at least one positive AND one
|
|
46
|
+
false-positive/negative case (e.g. the same word inside `echo '...'`).
|
|
47
|
+
4. **Update the `__init__.py` docstring** inventory.
|
|
48
|
+
5. `ruff check --fix` and `ruff format .`, then run the tests.
|
|
49
|
+
|
|
50
|
+
## Non-negotiable conventions
|
|
51
|
+
|
|
52
|
+
- **`pattern_name` is an API contract.** It is (a) shown to the user and
|
|
53
|
+
(b) the exact key users put in `dangerous_command_guard_allow`. Renaming one
|
|
54
|
+
silently breaks people's allowlists. Treat renames as breaking changes.
|
|
55
|
+
- **Detector stays pure.** No config reads, no `emit_*`, no network, no
|
|
56
|
+
filesystem. All side effects belong in `register_callbacks.py`. This keeps
|
|
57
|
+
the detector trivially unit-testable and fast.
|
|
58
|
+
- **False positives are worse than they look.** A too-greedy regex trains
|
|
59
|
+
users to reflexively approve prompts, which defeats the guard. Anchor
|
|
60
|
+
carefully (`\b`, end-of-string `$`), and always add a `_miss` test proving
|
|
61
|
+
safe look-alikes (`rm -i`, `git reset --soft`, `echo 'rm -rf /'`) don't fire.
|
|
62
|
+
- **Fail closed on ambiguity, fail open on our own errors.** If a command
|
|
63
|
+
looks destructive, block/prompt. But never let the guard crash the app —
|
|
64
|
+
the `run_shell_command` hook must degrade gracefully.
|
|
65
|
+
- **Cross-platform.** Patterns cover Unix, PowerShell, and CMD. New coverage
|
|
66
|
+
should consider all three where the operation exists.
|
|
67
|
+
- **Emojis in prompt strings are intentional** in `register_callbacks.py`
|
|
68
|
+
(the panel UI). Don't strip them when editing nearby lines.
|
|
69
|
+
- **600-line hard cap per file**; split into submodules if a file outgrows it.
|
|
70
|
+
- Run `ruff check --fix` and `ruff format .` before committing.
|
|
71
|
+
- **Never add a Claude / AI co-author trailer to commits.**
|
|
72
|
+
|
|
73
|
+
## Quick test commands
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
# detector + allowlist + callback behavior
|
|
77
|
+
pytest tests/plugins/test_destructive_command_detector.py \
|
|
78
|
+
tests/plugins/test_command_guard_allowlist.py -o addopts="" -q
|
|
79
|
+
```
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""Destructive command guard plugin.
|
|
2
|
+
|
|
3
|
+
Intercepts potentially-destructive shell commands and prompts the user for
|
|
4
|
+
approval before allowing them through. Always active, pure regex, no LLM calls.
|
|
5
|
+
|
|
6
|
+
Covers:
|
|
7
|
+
- Unix/Linux: rm -rf /, rm -rf ~, rm -rf /*, rm -rf ~/*
|
|
8
|
+
- Cross-platform (git, docker, npm/yarn, twine, SQL clients):
|
|
9
|
+
git push --mirror, git clean -fd, git reset --hard, git checkout/restore .,
|
|
10
|
+
DROP via SQL client, docker prune, npm/yarn publish, twine upload
|
|
11
|
+
- Windows PowerShell: Remove-Item -Recurse -Force, Format-Volume, Clear-Disk,
|
|
12
|
+
Remove-ItemProperty, Clear-RecycleBin, irm | iex (remote code execution)
|
|
13
|
+
- Windows CMD: rd /s /q, del /s system files, format, diskpart, bcdedit, reg delete
|
|
14
|
+
"""
|