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,212 @@
|
|
|
1
|
+
"""Map code-puppy lifecycle events onto herdr's three semantic states.
|
|
2
|
+
|
|
3
|
+
herdr models every agent as ``working`` / ``blocked`` / ``idle``. This
|
|
4
|
+
reporter is the single writer of that state for the pane, and code-puppy
|
|
5
|
+
reports it *authoritatively* -- herdr never has to infer our state from the
|
|
6
|
+
screen.
|
|
7
|
+
|
|
8
|
+
State is a pure function of two facts we own directly:
|
|
9
|
+
|
|
10
|
+
* **run depth** -- how many agent runs are in flight (root + sub-agents).
|
|
11
|
+
``> 0`` means the model is doing work.
|
|
12
|
+
* **awaiting** -- whether code-puppy is parked on the human. This comes from
|
|
13
|
+
the ``awaiting_user_input`` callback, which fires from the *one*
|
|
14
|
+
process-wide choke-point every interactive wait passes through
|
|
15
|
+
(shell-command approval, file-permission approval, ``ask_user_question``,
|
|
16
|
+
and every menu/picker). Because that single source covers every prompt --
|
|
17
|
+
including shell-command approval, which prompts from inside the tool -- the
|
|
18
|
+
plugin sees every block directly. There is nothing left for herdr to guess.
|
|
19
|
+
|
|
20
|
+
Effective state::
|
|
21
|
+
|
|
22
|
+
blocked if awaiting (parked on the human)
|
|
23
|
+
working elif run_depth > 0 (a run is in flight)
|
|
24
|
+
idle otherwise (control is the human's)
|
|
25
|
+
|
|
26
|
+
Sub-agents fire the same ``agent_run_start`` / ``agent_run_end`` hooks as the
|
|
27
|
+
root agent, so we refcount active runs (the same pattern the puppy_spinner
|
|
28
|
+
plugin uses) rather than flipping idle when a sub-agent finishes.
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
from __future__ import annotations
|
|
32
|
+
|
|
33
|
+
import logging
|
|
34
|
+
import threading
|
|
35
|
+
from typing import Optional, Tuple
|
|
36
|
+
|
|
37
|
+
from .client import HerdrClient
|
|
38
|
+
from . import sources
|
|
39
|
+
|
|
40
|
+
logger = logging.getLogger(__name__)
|
|
41
|
+
|
|
42
|
+
WORKING = "working"
|
|
43
|
+
BLOCKED = "blocked"
|
|
44
|
+
IDLE = "idle"
|
|
45
|
+
|
|
46
|
+
# Decorative activity strings (the ``message`` field on ``pane.report_agent``).
|
|
47
|
+
# State stays authoritative; these are best-effort colour commentary.
|
|
48
|
+
THINKING = "thinking"
|
|
49
|
+
AWAITING = "awaiting input"
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class HerdrReporter:
|
|
53
|
+
"""Thread-safe, dedup-ing bridge from callbacks to :class:`HerdrClient`."""
|
|
54
|
+
|
|
55
|
+
def __init__(self, client: HerdrClient) -> None:
|
|
56
|
+
self._client = client
|
|
57
|
+
self._lock = threading.Lock()
|
|
58
|
+
self._run_depth = 0
|
|
59
|
+
self._awaiting = False
|
|
60
|
+
self._awaiting_notify = True
|
|
61
|
+
self._last_reported_state: Optional[str] = None
|
|
62
|
+
self._last_reported_message: Optional[str] = None
|
|
63
|
+
# Latest working activity (``thinking`` / ``running <tool>``). Only
|
|
64
|
+
# surfaces while WORKING; BLOCKED and IDLE derive their own message.
|
|
65
|
+
self._activity: Optional[str] = None
|
|
66
|
+
# Durable session reference (name, pickle_path) — NOT the per-run group_id UUID,
|
|
67
|
+
# which changes every turn and can't identify a resumable session.
|
|
68
|
+
self._session_ref: Optional[Tuple[str, str]] = None
|
|
69
|
+
|
|
70
|
+
@property
|
|
71
|
+
def active(self) -> bool:
|
|
72
|
+
return self._client.active
|
|
73
|
+
|
|
74
|
+
# -- state derivation ----------------------------------------------
|
|
75
|
+
|
|
76
|
+
def _recompute_locked(self) -> Optional[str]:
|
|
77
|
+
"""Return the effective state from the facts we hold. Caller holds lock."""
|
|
78
|
+
if self._awaiting:
|
|
79
|
+
return BLOCKED
|
|
80
|
+
if self._run_depth > 0:
|
|
81
|
+
return WORKING
|
|
82
|
+
return IDLE
|
|
83
|
+
|
|
84
|
+
def _message_for_locked(self, state: str) -> Optional[str]:
|
|
85
|
+
"""Derive the decorative message for a state. Caller holds lock."""
|
|
86
|
+
if state == BLOCKED:
|
|
87
|
+
return AWAITING
|
|
88
|
+
if state == WORKING:
|
|
89
|
+
return self._activity or THINKING
|
|
90
|
+
return None
|
|
91
|
+
|
|
92
|
+
def _sync(self) -> None:
|
|
93
|
+
"""Report a changed (state, message) pair, optionally suppressing blocked.
|
|
94
|
+
|
|
95
|
+
A genuine state edge rides the critical lane; a message-only change
|
|
96
|
+
(same state, new activity) rides the decorative lane so it can never
|
|
97
|
+
delay an authoritative edge. User-initiated menus retain
|
|
98
|
+
``notify=False`` for their whole lifetime: their internal ``blocked``
|
|
99
|
+
state must not touch the edge trackers, so closing the menu does not
|
|
100
|
+
re-send an unchanged state.
|
|
101
|
+
"""
|
|
102
|
+
with self._lock:
|
|
103
|
+
state = self._recompute_locked()
|
|
104
|
+
if state == BLOCKED and not self._awaiting_notify:
|
|
105
|
+
return
|
|
106
|
+
message = self._message_for_locked(state)
|
|
107
|
+
state_changed = state != self._last_reported_state
|
|
108
|
+
message_changed = message != self._last_reported_message
|
|
109
|
+
if not state_changed and not message_changed:
|
|
110
|
+
return
|
|
111
|
+
self._last_reported_state = state
|
|
112
|
+
self._last_reported_message = message
|
|
113
|
+
session_id = self._session_ref[0] if self._session_ref else None
|
|
114
|
+
critical = state_changed
|
|
115
|
+
self._client.report_state(state, session_id, message=message, critical=critical)
|
|
116
|
+
|
|
117
|
+
def _refresh_session(self) -> None:
|
|
118
|
+
"""Resolve the durable session reference and report it on change.
|
|
119
|
+
|
|
120
|
+
Ignores per-run group_ids entirely. Resolution happens OUTSIDE the
|
|
121
|
+
lock (guardrail). The next prompt after ``/clear``, ``/session new``,
|
|
122
|
+
``/autosave_load``, ``/load_context``, a quick resume, or an agent
|
|
123
|
+
switch refreshes herdr with no core session callback.
|
|
124
|
+
"""
|
|
125
|
+
ref = sources.current_session_ref()
|
|
126
|
+
if ref is None:
|
|
127
|
+
return
|
|
128
|
+
with self._lock:
|
|
129
|
+
changed = ref != self._session_ref
|
|
130
|
+
self._session_ref = ref
|
|
131
|
+
if changed:
|
|
132
|
+
self._client.report_session(ref[0], ref[1])
|
|
133
|
+
|
|
134
|
+
# -- lifecycle handlers (all sync; safe from async or worker threads) --
|
|
135
|
+
|
|
136
|
+
def on_startup(self) -> None:
|
|
137
|
+
self._sync() # depth 0, not awaiting -> idle
|
|
138
|
+
|
|
139
|
+
def on_user_prompt(self, *_ignored) -> None:
|
|
140
|
+
# Ignore the callback's per-run group_id; resolve the durable session.
|
|
141
|
+
self._refresh_session()
|
|
142
|
+
|
|
143
|
+
def on_run_start(self, *_ignored) -> None:
|
|
144
|
+
with self._lock:
|
|
145
|
+
self._run_depth += 1
|
|
146
|
+
# The OUTER run starting is the canonical "thinking" edge. Nested
|
|
147
|
+
# sub-agent runs keep whatever activity is already showing.
|
|
148
|
+
if self._run_depth == 1:
|
|
149
|
+
self._activity = THINKING
|
|
150
|
+
self._sync()
|
|
151
|
+
|
|
152
|
+
def on_run_end(self, *_ignored) -> None:
|
|
153
|
+
with self._lock:
|
|
154
|
+
self._run_depth = max(0, self._run_depth - 1)
|
|
155
|
+
# Depth 0 = model stopped. The turn boundary is the canonical idle signal but
|
|
156
|
+
# headless (`-p`) runs never fire it, so depth-0 idle keeps panes honest too.
|
|
157
|
+
self._sync()
|
|
158
|
+
|
|
159
|
+
def on_run_cancel(self) -> None:
|
|
160
|
+
with self._lock:
|
|
161
|
+
self._run_depth = 0
|
|
162
|
+
self._awaiting = False
|
|
163
|
+
self._activity = None
|
|
164
|
+
self._sync()
|
|
165
|
+
|
|
166
|
+
def on_tool_start(self, tool_name: str) -> None:
|
|
167
|
+
"""A tool call started -> decorative ``running <tool>`` activity."""
|
|
168
|
+
# Resolve the message OUTSIDE the lock (guardrail: reporter locks
|
|
169
|
+
# never cover source resolution).
|
|
170
|
+
activity = sources.activity_message(tool_name)
|
|
171
|
+
with self._lock:
|
|
172
|
+
self._activity = activity
|
|
173
|
+
self._sync()
|
|
174
|
+
|
|
175
|
+
def on_tool_complete(self) -> None:
|
|
176
|
+
"""A tool call finished -> back to ``thinking`` while the run continues."""
|
|
177
|
+
with self._lock:
|
|
178
|
+
self._activity = THINKING
|
|
179
|
+
self._sync()
|
|
180
|
+
|
|
181
|
+
def on_turn_end(self) -> None:
|
|
182
|
+
with self._lock:
|
|
183
|
+
self._run_depth = 0
|
|
184
|
+
self._awaiting = False
|
|
185
|
+
self._activity = None
|
|
186
|
+
self._sync()
|
|
187
|
+
# A completed turn is the canonical metadata refresh point: payload computed
|
|
188
|
+
# once, outside the reporter lock, on the decorative lane. Sending every turn
|
|
189
|
+
# also refreshes the TTL; tool callbacks / blocked edges do no token math.
|
|
190
|
+
self._emit_metadata()
|
|
191
|
+
|
|
192
|
+
def _emit_metadata(self) -> None:
|
|
193
|
+
"""Compute and enqueue pane metadata. Never holds the reporter lock."""
|
|
194
|
+
payload = sources.current_tokens_payload()
|
|
195
|
+
if payload:
|
|
196
|
+
self._client.report_metadata(payload)
|
|
197
|
+
|
|
198
|
+
def on_awaiting_user_input(self, awaiting: bool, *, notify: bool = True) -> None:
|
|
199
|
+
"""Track an interactive wait, notifying only when requested."""
|
|
200
|
+
with self._lock:
|
|
201
|
+
self._awaiting = bool(awaiting)
|
|
202
|
+
self._awaiting_notify = bool(notify)
|
|
203
|
+
self._sync()
|
|
204
|
+
|
|
205
|
+
def on_shutdown(self) -> None:
|
|
206
|
+
# Release pane authority directly (no intermediate idle report).
|
|
207
|
+
# release_and_close() is idempotent and bounded, so calling it from both
|
|
208
|
+
# session_end and shutdown can never delay process exit.
|
|
209
|
+
self._client.release_and_close()
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
__all__ = ["HerdrReporter", "WORKING", "BLOCKED", "IDLE", "THINKING", "AWAITING"]
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"""Live smoke test for the herdr integration against a real herdr pane.
|
|
2
|
+
|
|
3
|
+
This is a **manual** verification tool, not part of the CI contract (the
|
|
4
|
+
unit tests in ``tests/plugins/test_herdr_*.py`` are). It exercises every
|
|
5
|
+
protocol-16 method the plugin uses -- ``pane.report_agent``,
|
|
6
|
+
``pane.report_agent_session``, ``pane.report_metadata``, and
|
|
7
|
+
``pane.release_agent`` -- against a live herdr server, and reads each result
|
|
8
|
+
back with ``herdr pane get`` to prove herdr actually stored it.
|
|
9
|
+
|
|
10
|
+
It is safe to run: it creates its OWN disposable pane, drives the real
|
|
11
|
+
``HerdrClient`` against that pane, and always closes it again -- your
|
|
12
|
+
working pane is never touched.
|
|
13
|
+
|
|
14
|
+
Usage (from inside a herdr pane)::
|
|
15
|
+
|
|
16
|
+
python -m code_puppy_core_plugins.herdr.smoke
|
|
17
|
+
|
|
18
|
+
Requires the ``herdr`` CLI on ``PATH`` and the ``HERDR_ENV`` /
|
|
19
|
+
``HERDR_SOCKET_PATH`` / ``HERDR_PANE_ID`` variables herdr injects. Exits 0
|
|
20
|
+
on success, 1 on any failed check, 2 on setup failure.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
from __future__ import annotations
|
|
24
|
+
|
|
25
|
+
import json
|
|
26
|
+
import os
|
|
27
|
+
import subprocess
|
|
28
|
+
import sys
|
|
29
|
+
import time
|
|
30
|
+
from typing import Any, Dict, Optional
|
|
31
|
+
|
|
32
|
+
_SPLIT_RATIO = 0.12
|
|
33
|
+
_SETTLE_S = 0.6
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _herdr(*args: str) -> Dict[str, Any]:
|
|
37
|
+
"""Run a herdr CLI command and parse its JSON reply."""
|
|
38
|
+
proc = subprocess.run(["herdr", *args], capture_output=True, text=True, timeout=10)
|
|
39
|
+
if not proc.stdout.strip():
|
|
40
|
+
raise RuntimeError(f"herdr {' '.join(args)} produced no output: {proc.stderr}")
|
|
41
|
+
return json.loads(proc.stdout)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _pane_field(pane_id: str, field: str) -> Any:
|
|
45
|
+
pane = _herdr("pane", "get", pane_id)["result"]["pane"]
|
|
46
|
+
return pane.get(field)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _create_disposable_pane(parent: str) -> str:
|
|
50
|
+
reply = _herdr(
|
|
51
|
+
"pane",
|
|
52
|
+
"split",
|
|
53
|
+
parent,
|
|
54
|
+
"--direction",
|
|
55
|
+
"down",
|
|
56
|
+
"--ratio",
|
|
57
|
+
str(_SPLIT_RATIO),
|
|
58
|
+
"--no-focus",
|
|
59
|
+
)
|
|
60
|
+
return reply["result"]["pane"]["pane_id"]
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _make_client(pane_id: str):
|
|
64
|
+
# Point a real client at the disposable pane. HERDR_SOCKET_PATH is
|
|
65
|
+
# inherited from the surrounding pane.
|
|
66
|
+
os.environ["HERDR_ENV"] = "1"
|
|
67
|
+
os.environ["HERDR_PANE_ID"] = pane_id
|
|
68
|
+
from code_puppy_core_plugins.herdr.client import HerdrClient
|
|
69
|
+
|
|
70
|
+
return HerdrClient()
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _run_checks(client, pane_id: str) -> Dict[str, bool]:
|
|
74
|
+
results: Dict[str, bool] = {}
|
|
75
|
+
|
|
76
|
+
client.report_state("working")
|
|
77
|
+
client.report_session("smoke_session_x", "/tmp/smoke_session_x.pkl")
|
|
78
|
+
client.report_metadata(
|
|
79
|
+
{"model": "claude-smoke", "context": "42%", "tokens": "48k/200k"}
|
|
80
|
+
)
|
|
81
|
+
time.sleep(_SETTLE_S)
|
|
82
|
+
results["state_working"] = _pane_field(pane_id, "agent_status") == "working"
|
|
83
|
+
results["metadata_tokens"] = bool(_pane_field(pane_id, "tokens"))
|
|
84
|
+
|
|
85
|
+
client.report_state("blocked")
|
|
86
|
+
time.sleep(_SETTLE_S)
|
|
87
|
+
results["state_blocked"] = _pane_field(pane_id, "agent_status") == "blocked"
|
|
88
|
+
|
|
89
|
+
client.report_state("idle")
|
|
90
|
+
time.sleep(_SETTLE_S)
|
|
91
|
+
results["state_idle"] = _pane_field(pane_id, "agent_status") == "idle"
|
|
92
|
+
|
|
93
|
+
started = time.monotonic()
|
|
94
|
+
client.release_and_close(timeout_s=1.0)
|
|
95
|
+
elapsed = time.monotonic() - started
|
|
96
|
+
results["release_bounded"] = elapsed < 1.5
|
|
97
|
+
time.sleep(_SETTLE_S)
|
|
98
|
+
# Releasing authority drops the pane back to 'unknown'.
|
|
99
|
+
results["release_clears_state"] = _pane_field(pane_id, "agent_status") == "unknown"
|
|
100
|
+
|
|
101
|
+
return results
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def main() -> int:
|
|
105
|
+
if os.environ.get("HERDR_ENV") != "1":
|
|
106
|
+
print("Not inside a herdr pane (HERDR_ENV != 1). Aborting.", file=sys.stderr)
|
|
107
|
+
return 2
|
|
108
|
+
parent = os.environ.get("HERDR_PANE_ID")
|
|
109
|
+
if not parent:
|
|
110
|
+
print("HERDR_PANE_ID is unset. Aborting.", file=sys.stderr)
|
|
111
|
+
return 2
|
|
112
|
+
|
|
113
|
+
pane_id: Optional[str] = None
|
|
114
|
+
try:
|
|
115
|
+
pane_id = _create_disposable_pane(parent)
|
|
116
|
+
print(f"Created disposable pane {pane_id} (from {parent})")
|
|
117
|
+
client = _make_client(pane_id)
|
|
118
|
+
if not client.active:
|
|
119
|
+
print("HerdrClient did not activate. Aborting.", file=sys.stderr)
|
|
120
|
+
return 2
|
|
121
|
+
results = _run_checks(client, pane_id)
|
|
122
|
+
except Exception as exc: # pragma: no cover - manual tool
|
|
123
|
+
print(f"Smoke setup/run error: {exc}", file=sys.stderr)
|
|
124
|
+
return 2
|
|
125
|
+
finally:
|
|
126
|
+
if pane_id:
|
|
127
|
+
try:
|
|
128
|
+
_herdr("pane", "close", pane_id)
|
|
129
|
+
print(f"Closed disposable pane {pane_id}")
|
|
130
|
+
except Exception as exc: # pragma: no cover - manual tool
|
|
131
|
+
print(f"WARNING: could not close {pane_id}: {exc}", file=sys.stderr)
|
|
132
|
+
|
|
133
|
+
print("\nResults:")
|
|
134
|
+
ok = True
|
|
135
|
+
for name, passed in results.items():
|
|
136
|
+
print(f" {'PASS' if passed else 'FAIL'} {name}")
|
|
137
|
+
ok = ok and passed
|
|
138
|
+
print("\nSMOKE " + ("PASSED" if ok else "FAILED"))
|
|
139
|
+
return 0 if ok else 1
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
if __name__ == "__main__":
|
|
143
|
+
raise SystemExit(main())
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"""Fail-soft adapters from code-puppy internals to herdr report payloads.
|
|
2
|
+
|
|
3
|
+
This is the single seam between the herdr plugin and the rest of
|
|
4
|
+
code-puppy. Every function here catches ordinary runtime failures, logs at
|
|
5
|
+
debug level, and returns a safe fallback -- reporting to herdr must never
|
|
6
|
+
be able to disturb the agent. Reporter/client code depends only on this
|
|
7
|
+
module's return shapes, and its tests mock this module.
|
|
8
|
+
|
|
9
|
+
Three adapters:
|
|
10
|
+
|
|
11
|
+
* :func:`current_tokens_payload` -- a static-keyed, string-valued map of
|
|
12
|
+
``model`` / ``context`` / ``tokens`` for ``pane.report_metadata``.
|
|
13
|
+
* :func:`current_session_ref` -- a stable ``(session_id, session_path)``
|
|
14
|
+
reference for ``pane.report_agent_session``.
|
|
15
|
+
* :func:`activity_message` -- a short human-readable activity string for
|
|
16
|
+
the decorative ``message`` field on ``pane.report_agent``.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
import logging
|
|
22
|
+
from typing import Dict, Optional, Tuple
|
|
23
|
+
|
|
24
|
+
logger = logging.getLogger(__name__)
|
|
25
|
+
|
|
26
|
+
#: herdr caps metadata values; keep every value comfortably short.
|
|
27
|
+
_MAX_VALUE_LEN = 128
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _compact_tokens(n: int) -> str:
|
|
31
|
+
"""Render a token count compactly: 999 -> ``999``; 48200 -> ``48k``."""
|
|
32
|
+
n = int(n)
|
|
33
|
+
if n < 1000:
|
|
34
|
+
return str(n)
|
|
35
|
+
if n < 1_000_000:
|
|
36
|
+
return f"{n // 1000}k"
|
|
37
|
+
return f"{n // 1_000_000}M"
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _clip(value: object) -> str:
|
|
41
|
+
"""Coerce to a string and cap length so a payload can't balloon."""
|
|
42
|
+
text = str(value)
|
|
43
|
+
return text[:_MAX_VALUE_LEN]
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _current_model() -> Optional[str]:
|
|
47
|
+
try:
|
|
48
|
+
from code_puppy.agents.agent_manager import get_current_agent
|
|
49
|
+
|
|
50
|
+
agent = get_current_agent()
|
|
51
|
+
if agent is None:
|
|
52
|
+
return None
|
|
53
|
+
return agent.get_model_name()
|
|
54
|
+
except Exception:
|
|
55
|
+
logger.debug("herdr: could not resolve current model", exc_info=True)
|
|
56
|
+
return None
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def current_tokens_payload() -> Optional[Dict[str, str]]:
|
|
60
|
+
"""Return a static-keyed metadata map, or ``None`` when unavailable.
|
|
61
|
+
|
|
62
|
+
Keys are always ``model``, ``context``, and ``tokens``; values are
|
|
63
|
+
coerced to strings and clipped. Indicator glyphs are omitted on purpose
|
|
64
|
+
-- herdr rows already carry their own state icons. Returns ``None`` if
|
|
65
|
+
context usage can't be computed so the pane keeps its last good values
|
|
66
|
+
(which the metadata TTL eventually clears).
|
|
67
|
+
"""
|
|
68
|
+
try:
|
|
69
|
+
from code_puppy.token_usage import get_current_usage
|
|
70
|
+
|
|
71
|
+
usage = get_current_usage()
|
|
72
|
+
if usage is None:
|
|
73
|
+
return None
|
|
74
|
+
payload: Dict[str, str] = {
|
|
75
|
+
"context": _clip(f"{round(usage.percent)}%"),
|
|
76
|
+
"tokens": _clip(
|
|
77
|
+
f"{_compact_tokens(usage.total_tokens)}/{_compact_tokens(usage.capacity)}"
|
|
78
|
+
),
|
|
79
|
+
}
|
|
80
|
+
model = _current_model()
|
|
81
|
+
if model:
|
|
82
|
+
payload["model"] = _clip(model)
|
|
83
|
+
return payload
|
|
84
|
+
except Exception:
|
|
85
|
+
logger.debug("herdr: token payload unavailable", exc_info=True)
|
|
86
|
+
return None
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def current_session_ref() -> Optional[Tuple[str, str]]:
|
|
90
|
+
"""Return ``(session_id, session_path)`` for the process's autosave.
|
|
91
|
+
|
|
92
|
+
The name is stable for the life of a session (until ``/clear``,
|
|
93
|
+
``/session new``, resume, load, or rotation), and the pickle path stays
|
|
94
|
+
canonical because the CLI pins the resolved stem and writes later saves
|
|
95
|
+
to ``AUTOSAVE_DIR``. Returns ``None`` on any failure.
|
|
96
|
+
"""
|
|
97
|
+
try:
|
|
98
|
+
from pathlib import Path
|
|
99
|
+
|
|
100
|
+
from code_puppy.config import AUTOSAVE_DIR, get_current_session_name
|
|
101
|
+
from code_puppy.session_storage import build_session_paths
|
|
102
|
+
|
|
103
|
+
name = get_current_session_name()
|
|
104
|
+
if not name:
|
|
105
|
+
return None
|
|
106
|
+
paths = build_session_paths(Path(AUTOSAVE_DIR), name)
|
|
107
|
+
return name, str(paths.pickle_path)
|
|
108
|
+
except Exception:
|
|
109
|
+
logger.debug("herdr: session ref unavailable", exc_info=True)
|
|
110
|
+
return None
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def activity_message(tool_name: str) -> str:
|
|
114
|
+
"""Return a short activity string for a starting tool call.
|
|
115
|
+
|
|
116
|
+
``read_file`` -> ``running read file``. Fail-soft: an odd or missing
|
|
117
|
+
name degrades to a generic ``running tool``.
|
|
118
|
+
"""
|
|
119
|
+
try:
|
|
120
|
+
humanized = str(tool_name).replace("_", " ").strip()
|
|
121
|
+
if not humanized:
|
|
122
|
+
return "running tool"
|
|
123
|
+
return f"running {humanized}"
|
|
124
|
+
except Exception:
|
|
125
|
+
logger.debug("herdr: could not humanize tool name", exc_info=True)
|
|
126
|
+
return "running tool"
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
__all__ = [
|
|
130
|
+
"current_tokens_payload",
|
|
131
|
+
"current_session_ref",
|
|
132
|
+
"activity_message",
|
|
133
|
+
]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Hook Creator Plugin
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Hook Creator Plugin - Simple command that injects MCP prompt
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from code_puppy.callbacks import register_callback
|
|
6
|
+
from code_puppy.mcp_prompts.hook_creator import HOOK_CREATION_PROMPT
|
|
7
|
+
from code_puppy.messaging import emit_info
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def _custom_help():
|
|
11
|
+
"""Help entries for create-hook commands."""
|
|
12
|
+
return [
|
|
13
|
+
("create-hook", "Get help creating Code Puppy hooks"),
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _handle_custom_command(command: str, name: str):
|
|
18
|
+
"""Handle /create-hook command.
|
|
19
|
+
|
|
20
|
+
Displays hook creation documentation and sends to model with context.
|
|
21
|
+
"""
|
|
22
|
+
if name != "create-hook":
|
|
23
|
+
return None
|
|
24
|
+
|
|
25
|
+
emit_info(HOOK_CREATION_PROMPT)
|
|
26
|
+
|
|
27
|
+
# Send the prompt to the model with the hook docs as context
|
|
28
|
+
return "I need help creating a hook for Code Puppy. Here's the documentation above. Can you help me?"
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
# Register the custom command
|
|
32
|
+
register_callback("custom_command_help", _custom_help)
|
|
33
|
+
register_callback("custom_command", _handle_custom_command)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Hook Manager plugin – interactive TUI for managing Claude Code hooks."""
|