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,219 @@
|
|
|
1
|
+
"""Skill metadata parsing - extracts info from SKILL.md frontmatter."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
import re
|
|
5
|
+
from dataclasses import dataclass, field
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import List, Optional
|
|
8
|
+
|
|
9
|
+
logger = logging.getLogger(__name__)
|
|
10
|
+
|
|
11
|
+
# Regex pattern to match YAML frontmatter between --- delimiters
|
|
12
|
+
FRONTMATTER_PATTERN = re.compile(r"^---\s*\n(.*?)\n---\s*\n", re.DOTALL)
|
|
13
|
+
|
|
14
|
+
# Regex patterns for parsing simple key-value pairs from YAML-like frontmatter
|
|
15
|
+
KEY_VALUE_PATTERN = re.compile(r"^([a-zA-Z_][a-zA-Z0-9_]*):\s*(.*)$", re.MULTILINE)
|
|
16
|
+
LIST_PATTERN = re.compile(r"^\s+-\s+(.+)$", re.MULTILINE)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@dataclass
|
|
20
|
+
class SkillMetadata:
|
|
21
|
+
"""Parsed skill metadata from SKILL.md frontmatter."""
|
|
22
|
+
|
|
23
|
+
name: str
|
|
24
|
+
description: str
|
|
25
|
+
path: Path
|
|
26
|
+
version: Optional[str] = None
|
|
27
|
+
author: Optional[str] = None
|
|
28
|
+
tags: List[str] = field(default_factory=list)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _unquote(value: str) -> str:
|
|
32
|
+
"""Remove quotes from a YAML string value if present."""
|
|
33
|
+
value = value.strip()
|
|
34
|
+
if (value.startswith('"') and value.endswith('"')) or (
|
|
35
|
+
value.startswith("'") and value.endswith("'")
|
|
36
|
+
):
|
|
37
|
+
return value[1:-1]
|
|
38
|
+
return value
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def parse_yaml_frontmatter(content: str) -> dict:
|
|
42
|
+
"""Extract YAML frontmatter from SKILL.md content.
|
|
43
|
+
|
|
44
|
+
Frontmatter is between --- delimiters at the start of file.
|
|
45
|
+
Uses simple regex parsing to avoid heavy yaml dependency.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
content: The full content of the SKILL.md file.
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
Dictionary containing parsed frontmatter key-value pairs.
|
|
52
|
+
Returns empty dict if no frontmatter found or parsing fails.
|
|
53
|
+
"""
|
|
54
|
+
match = FRONTMATTER_PATTERN.match(content)
|
|
55
|
+
if not match:
|
|
56
|
+
logger.debug("No frontmatter found in content")
|
|
57
|
+
return {}
|
|
58
|
+
|
|
59
|
+
frontmatter = match.group(1)
|
|
60
|
+
result: dict = {}
|
|
61
|
+
current_key: Optional[str] = None
|
|
62
|
+
current_list: List[str] = []
|
|
63
|
+
|
|
64
|
+
for line in frontmatter.split("\n"):
|
|
65
|
+
stripped = line.strip()
|
|
66
|
+
|
|
67
|
+
# Skip empty lines and comments
|
|
68
|
+
if not stripped or stripped.startswith("#"):
|
|
69
|
+
continue
|
|
70
|
+
|
|
71
|
+
# Check if this is a list item
|
|
72
|
+
list_match = LIST_PATTERN.match(line)
|
|
73
|
+
if list_match and current_key:
|
|
74
|
+
current_list.append(_unquote(list_match.group(1)))
|
|
75
|
+
continue
|
|
76
|
+
|
|
77
|
+
# Check if this is a key-value pair
|
|
78
|
+
kv_match = KEY_VALUE_PATTERN.match(line)
|
|
79
|
+
if kv_match:
|
|
80
|
+
# Save any accumulated list items from previous key
|
|
81
|
+
if current_key and current_list:
|
|
82
|
+
result[current_key] = current_list
|
|
83
|
+
current_list = []
|
|
84
|
+
|
|
85
|
+
key, value = kv_match.groups()
|
|
86
|
+
key = key.strip()
|
|
87
|
+
value = value.strip()
|
|
88
|
+
|
|
89
|
+
# If value is empty, this might be a list start
|
|
90
|
+
if not value:
|
|
91
|
+
current_key = key
|
|
92
|
+
result[key] = [] # Initialize as empty list
|
|
93
|
+
else:
|
|
94
|
+
result[key] = _unquote(value)
|
|
95
|
+
current_key = None
|
|
96
|
+
|
|
97
|
+
# Handle case where list items were at the end
|
|
98
|
+
if current_key and current_list:
|
|
99
|
+
result[current_key] = current_list
|
|
100
|
+
|
|
101
|
+
return result
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def parse_skill_metadata(skill_path: Path) -> Optional[SkillMetadata]:
|
|
105
|
+
"""Parse metadata from a skill's SKILL.md file.
|
|
106
|
+
|
|
107
|
+
Args:
|
|
108
|
+
skill_path: Path to the skill directory (not the SKILL.md file)
|
|
109
|
+
|
|
110
|
+
Returns:
|
|
111
|
+
SkillMetadata if successful, None if parsing fails.
|
|
112
|
+
"""
|
|
113
|
+
if not skill_path.exists():
|
|
114
|
+
logger.debug(f"Skill path does not exist: {skill_path}")
|
|
115
|
+
return None
|
|
116
|
+
|
|
117
|
+
skill_md_path = skill_path / "SKILL.md"
|
|
118
|
+
if not skill_md_path.exists():
|
|
119
|
+
logger.debug(f"SKILL.md not found in skill directory: {skill_path}")
|
|
120
|
+
return None
|
|
121
|
+
|
|
122
|
+
try:
|
|
123
|
+
content = skill_md_path.read_text(encoding="utf-8")
|
|
124
|
+
except Exception as e:
|
|
125
|
+
logger.error(f"Failed to read SKILL.md at {skill_md_path}: {e}")
|
|
126
|
+
return None
|
|
127
|
+
|
|
128
|
+
frontmatter = parse_yaml_frontmatter(content)
|
|
129
|
+
if not frontmatter:
|
|
130
|
+
logger.debug(f"No valid frontmatter found in {skill_md_path}")
|
|
131
|
+
return None
|
|
132
|
+
|
|
133
|
+
# Required fields
|
|
134
|
+
name = frontmatter.get("name")
|
|
135
|
+
if not name:
|
|
136
|
+
logger.debug(
|
|
137
|
+
f"'name' is required in frontmatter but not found in {skill_md_path}"
|
|
138
|
+
)
|
|
139
|
+
return None
|
|
140
|
+
|
|
141
|
+
description = frontmatter.get("description")
|
|
142
|
+
if not description:
|
|
143
|
+
logger.debug(
|
|
144
|
+
f"'description' is required in frontmatter but not found in {skill_md_path}"
|
|
145
|
+
)
|
|
146
|
+
return None
|
|
147
|
+
|
|
148
|
+
# Handle tags - could be a list or a comma-separated string
|
|
149
|
+
tags: List[str] = []
|
|
150
|
+
raw_tags = frontmatter.get("tags", [])
|
|
151
|
+
if isinstance(raw_tags, list):
|
|
152
|
+
tags = raw_tags
|
|
153
|
+
elif isinstance(raw_tags, str):
|
|
154
|
+
tags = [tag.strip() for tag in raw_tags.split(",") if tag.strip()]
|
|
155
|
+
|
|
156
|
+
return SkillMetadata(
|
|
157
|
+
name=name,
|
|
158
|
+
description=description,
|
|
159
|
+
path=skill_path,
|
|
160
|
+
version=frontmatter.get("version"),
|
|
161
|
+
author=frontmatter.get("author"),
|
|
162
|
+
tags=tags,
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def load_full_skill_content(skill_path: Path) -> Optional[str]:
|
|
167
|
+
"""Load the complete SKILL.md content for activation.
|
|
168
|
+
|
|
169
|
+
Args:
|
|
170
|
+
skill_path: Path to the skill directory
|
|
171
|
+
|
|
172
|
+
Returns:
|
|
173
|
+
Full file content as string, or None if not found.
|
|
174
|
+
"""
|
|
175
|
+
if not skill_path.exists():
|
|
176
|
+
logger.debug(f"Skill path does not exist: {skill_path}")
|
|
177
|
+
return None
|
|
178
|
+
|
|
179
|
+
skill_md_path = skill_path / "SKILL.md"
|
|
180
|
+
if not skill_md_path.exists():
|
|
181
|
+
logger.debug(f"SKILL.md not found in skill directory: {skill_path}")
|
|
182
|
+
return None
|
|
183
|
+
|
|
184
|
+
try:
|
|
185
|
+
return skill_md_path.read_text(encoding="utf-8")
|
|
186
|
+
except Exception as e:
|
|
187
|
+
logger.error(f"Failed to read SKILL.md at {skill_md_path}: {e}")
|
|
188
|
+
return None
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def get_skill_resources(skill_path: Path) -> List[Path]:
|
|
192
|
+
"""List all resource files bundled with a skill.
|
|
193
|
+
|
|
194
|
+
Returns paths to all non-SKILL.md files in the skill directory.
|
|
195
|
+
|
|
196
|
+
Args:
|
|
197
|
+
skill_path: Path to the skill directory
|
|
198
|
+
|
|
199
|
+
Returns:
|
|
200
|
+
List of paths to resource files (excluding SKILL.md).
|
|
201
|
+
"""
|
|
202
|
+
if not skill_path.exists():
|
|
203
|
+
logger.debug(f"Skill path does not exist: {skill_path}")
|
|
204
|
+
return []
|
|
205
|
+
|
|
206
|
+
if not skill_path.is_dir():
|
|
207
|
+
logger.warning(f"Skill path is not a directory: {skill_path}")
|
|
208
|
+
return []
|
|
209
|
+
|
|
210
|
+
resources: List[Path] = []
|
|
211
|
+
try:
|
|
212
|
+
for item in skill_path.iterdir():
|
|
213
|
+
if item.is_file() and item.name != "SKILL.md":
|
|
214
|
+
resources.append(item)
|
|
215
|
+
except Exception as e:
|
|
216
|
+
logger.error(f"Failed to list resources in {skill_path}: {e}")
|
|
217
|
+
return []
|
|
218
|
+
|
|
219
|
+
return sorted(resources) # Sort for consistent ordering
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"""Build the `available skills` section for system-prompt injection.
|
|
2
|
+
|
|
3
|
+
Keep the verbosity floor-low. Each skill becomes a single line of the form
|
|
4
|
+
``- <name>: <description>``. That is essentially the frontmatter `name` and
|
|
5
|
+
`description` fields, flattened. No XML, no ceremony, no escaping circus.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import TYPE_CHECKING, List
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from .metadata import SkillMetadata
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _one_line(text: str) -> str:
|
|
15
|
+
"""Collapse whitespace so each skill stays on a single line."""
|
|
16
|
+
return " ".join(text.split())
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def build_available_skills_block(skills: List["SkillMetadata"]) -> str:
|
|
20
|
+
"""Render a minimal markdown list of available skills.
|
|
21
|
+
|
|
22
|
+
Format::
|
|
23
|
+
|
|
24
|
+
## Available Skills
|
|
25
|
+
- skill-one: short description
|
|
26
|
+
- skill-two: short description
|
|
27
|
+
|
|
28
|
+
Returns an empty string when there are no skills — callers can simply
|
|
29
|
+
concatenate without worrying about stray headings.
|
|
30
|
+
"""
|
|
31
|
+
if not skills:
|
|
32
|
+
return ""
|
|
33
|
+
|
|
34
|
+
lines = ["## Available Skills"]
|
|
35
|
+
for skill in skills:
|
|
36
|
+
desc = _one_line(skill.description) if skill.description else ""
|
|
37
|
+
lines.append(f"- {skill.name}: {desc}" if desc else f"- {skill.name}")
|
|
38
|
+
return "\n".join(lines)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def build_skills_guidance() -> str:
|
|
42
|
+
"""Tell the model when and how to use a skill."""
|
|
43
|
+
return (
|
|
44
|
+
"When the user's question or task relates to a skill listed above, "
|
|
45
|
+
"activate it with `activate_skill(name)` **before** answering so its "
|
|
46
|
+
"full instructions are loaded into context. Use "
|
|
47
|
+
"`list_or_search_skills(query)` to discover skills by keyword — it "
|
|
48
|
+
"matches any individual word in the query."
|
|
49
|
+
)
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"""Core-facing provider backed by the agent_skills plugin's existing helpers."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Any, List, Optional, Set
|
|
7
|
+
|
|
8
|
+
from .config import get_disabled_skills, get_skills_enabled
|
|
9
|
+
from .enabled_skills import iter_enabled_skills, list_enabled_skill_metadata
|
|
10
|
+
from .metadata import get_skill_resources, load_full_skill_content
|
|
11
|
+
from .skill_catalog import catalog
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class AgentSkillsProvider:
|
|
15
|
+
"""Adapt agent_skills internals to the neutral core provider contract."""
|
|
16
|
+
|
|
17
|
+
def is_enabled(self) -> bool:
|
|
18
|
+
return get_skills_enabled()
|
|
19
|
+
|
|
20
|
+
def get_disabled_skill_names(self) -> Set[str]:
|
|
21
|
+
return get_disabled_skills()
|
|
22
|
+
|
|
23
|
+
def list_enabled_skills(self) -> List[dict[str, Any]]:
|
|
24
|
+
return [
|
|
25
|
+
{
|
|
26
|
+
"name": metadata.name,
|
|
27
|
+
"description": metadata.description,
|
|
28
|
+
"path": str(metadata.path),
|
|
29
|
+
"tags": metadata.tags,
|
|
30
|
+
"version": metadata.version,
|
|
31
|
+
"author": metadata.author,
|
|
32
|
+
}
|
|
33
|
+
for metadata in list_enabled_skill_metadata()
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
def find_enabled_skill_path(self, skill_name: str) -> Optional[Path]:
|
|
37
|
+
return next(
|
|
38
|
+
(info.path for info in iter_enabled_skills() if info.name == skill_name),
|
|
39
|
+
None,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
def load_skill_content(self, skill_path: Path) -> Optional[str]:
|
|
43
|
+
return load_full_skill_content(skill_path)
|
|
44
|
+
|
|
45
|
+
def get_skill_resources(self, skill_path: Path) -> List[Path]:
|
|
46
|
+
return get_skill_resources(skill_path)
|
|
47
|
+
|
|
48
|
+
def get_catalog_skill_ids(self) -> List[str]:
|
|
49
|
+
return [entry.id for entry in catalog.get_all()]
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
skill_provider = AgentSkillsProvider()
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
"""Agent Skills plugin - registers callbacks for skill integration.
|
|
2
|
+
|
|
3
|
+
This plugin:
|
|
4
|
+
1. Injects available skills into system prompts
|
|
5
|
+
2. Registers skill-related tools
|
|
6
|
+
3. Exposes a skills provider via the ``register_skills`` hook
|
|
7
|
+
4. Provides /skills slash command (and alias /skill)
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import logging
|
|
11
|
+
from typing import Any, Dict, List, Optional, Tuple
|
|
12
|
+
|
|
13
|
+
from code_puppy.callbacks import register_callback
|
|
14
|
+
|
|
15
|
+
logger = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _get_skills_prompt_section() -> Optional[str]:
|
|
19
|
+
"""Build the skills section to inject into system prompts.
|
|
20
|
+
|
|
21
|
+
Returns None if skills are disabled or no enabled skills exist.
|
|
22
|
+
Disabled skills never have their frontmatter loaded — see
|
|
23
|
+
:mod:`code_puppy_core_plugins.agent_skills.enabled_skills`.
|
|
24
|
+
|
|
25
|
+
When ``frontmatter_in_system_prompt`` is ``False``, the per-skill list is
|
|
26
|
+
omitted but the short guidance line is still emitted so the model knows
|
|
27
|
+
the ``activate_skill`` / ``list_or_search_skills`` mechanism exists.
|
|
28
|
+
"""
|
|
29
|
+
from .config import get_frontmatter_in_system_prompt
|
|
30
|
+
from .enabled_skills import list_enabled_skill_metadata
|
|
31
|
+
from .prompt_builder import build_available_skills_block, build_skills_guidance
|
|
32
|
+
|
|
33
|
+
skills_metadata = list_enabled_skill_metadata()
|
|
34
|
+
if not skills_metadata:
|
|
35
|
+
logger.debug("No enabled skills with metadata found, skipping prompt injection")
|
|
36
|
+
return None
|
|
37
|
+
|
|
38
|
+
guidance = build_skills_guidance()
|
|
39
|
+
|
|
40
|
+
if not get_frontmatter_in_system_prompt():
|
|
41
|
+
logger.debug(
|
|
42
|
+
"Frontmatter injection disabled; emitting guidance line only "
|
|
43
|
+
f"({len(skills_metadata)} skills hidden from system prompt)"
|
|
44
|
+
)
|
|
45
|
+
return guidance
|
|
46
|
+
|
|
47
|
+
skills_block = build_available_skills_block(skills_metadata)
|
|
48
|
+
logger.debug(f"Injecting skills section with {len(skills_metadata)} skills")
|
|
49
|
+
return f"{skills_block}\n\n{guidance}"
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _inject_skills_into_prompt(
|
|
53
|
+
model_name: str, default_system_prompt: str, user_prompt: str
|
|
54
|
+
) -> Optional[Dict[str, Any]]:
|
|
55
|
+
"""Callback to inject skills into system prompt.
|
|
56
|
+
|
|
57
|
+
This is registered with the 'get_model_system_prompt' callback phase.
|
|
58
|
+
"""
|
|
59
|
+
skills_section = _get_skills_prompt_section()
|
|
60
|
+
|
|
61
|
+
if not skills_section:
|
|
62
|
+
return None # No skills, don't modify prompt
|
|
63
|
+
|
|
64
|
+
# Append skills section to system prompt
|
|
65
|
+
enhanced_prompt = f"{default_system_prompt}\n\n{skills_section}"
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
"instructions": enhanced_prompt,
|
|
69
|
+
"user_prompt": user_prompt,
|
|
70
|
+
"handled": False, # Let other handlers also process
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def _register_skills_tools() -> List[Dict[str, Any]]:
|
|
75
|
+
"""Callback to register skills tools.
|
|
76
|
+
|
|
77
|
+
This is registered with the 'register_tools' callback phase.
|
|
78
|
+
Returns tool definitions for the tool registry.
|
|
79
|
+
"""
|
|
80
|
+
from code_puppy.tools.skills_tools import (
|
|
81
|
+
register_activate_skill,
|
|
82
|
+
register_list_or_search_skills,
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
return [
|
|
86
|
+
{"name": "activate_skill", "register_func": register_activate_skill},
|
|
87
|
+
{
|
|
88
|
+
"name": "list_or_search_skills",
|
|
89
|
+
"register_func": register_list_or_search_skills,
|
|
90
|
+
},
|
|
91
|
+
]
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def _register_skills() -> List[Dict[str, Any]]:
|
|
95
|
+
"""Expose the plugin through the neutral ``register_skills`` provider seam."""
|
|
96
|
+
from .provider import skill_provider
|
|
97
|
+
|
|
98
|
+
return [{"provider": skill_provider}]
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
# ---------------------------------------------------------------------------
|
|
102
|
+
# Slash command: /skills (and alias /skill)
|
|
103
|
+
# ---------------------------------------------------------------------------
|
|
104
|
+
|
|
105
|
+
_COMMAND_NAME = "skills"
|
|
106
|
+
_ALIASES = ("skill",)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def _skills_command_help() -> List[Tuple[str, str]]:
|
|
110
|
+
"""Advertise /skills (+ every individual skill) in the /help menu."""
|
|
111
|
+
from .skill_commands import skill_command_help
|
|
112
|
+
|
|
113
|
+
entries: List[Tuple[str, str]] = [
|
|
114
|
+
("skills", "Manage agent skills – browse, enable, disable, install"),
|
|
115
|
+
("skill", "Alias for /skills"),
|
|
116
|
+
]
|
|
117
|
+
# Append per-skill commands so they show up in /help & tab-completion.
|
|
118
|
+
entries.extend(skill_command_help())
|
|
119
|
+
return entries
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def _handle_skills_command(command: str, name: str) -> Optional[Any]:
|
|
123
|
+
"""Handle /skills and /skill slash commands.
|
|
124
|
+
|
|
125
|
+
Sub-commands:
|
|
126
|
+
/skills – Launch interactive TUI menu
|
|
127
|
+
/skills list – Quick text list of all skills
|
|
128
|
+
/skills install – Browse & install from remote catalog
|
|
129
|
+
/skills enable – Enable skills integration globally
|
|
130
|
+
/skills disable – Disable skills integration globally
|
|
131
|
+
/skills toggle – Toggle skills integration globally
|
|
132
|
+
/skills refresh – Force skill re-discovery and refresh local cache
|
|
133
|
+
/skills help – Show skills command help
|
|
134
|
+
"""
|
|
135
|
+
if name not in (_COMMAND_NAME, *_ALIASES):
|
|
136
|
+
# Not the /skills meta-command — maybe it's an individual skill?
|
|
137
|
+
from .skill_commands import handle_skill_command
|
|
138
|
+
|
|
139
|
+
return handle_skill_command(command, name)
|
|
140
|
+
|
|
141
|
+
from code_puppy.messaging import emit_error, emit_info, emit_success, emit_warning
|
|
142
|
+
from code_puppy_core_plugins.agent_skills.config import (
|
|
143
|
+
get_disabled_skills,
|
|
144
|
+
get_frontmatter_in_system_prompt,
|
|
145
|
+
get_skills_enabled,
|
|
146
|
+
set_frontmatter_in_system_prompt,
|
|
147
|
+
set_skills_enabled,
|
|
148
|
+
)
|
|
149
|
+
from code_puppy_core_plugins.agent_skills.discovery import (
|
|
150
|
+
discover_skills,
|
|
151
|
+
refresh_skill_cache,
|
|
152
|
+
)
|
|
153
|
+
from code_puppy_core_plugins.agent_skills.metadata import parse_skill_metadata
|
|
154
|
+
from code_puppy_core_plugins.agent_skills.skills_menu import show_skills_menu
|
|
155
|
+
|
|
156
|
+
tokens = command.split()
|
|
157
|
+
|
|
158
|
+
if len(tokens) > 1:
|
|
159
|
+
subcommand = tokens[1].lower()
|
|
160
|
+
|
|
161
|
+
if subcommand == "list":
|
|
162
|
+
disabled_skills = get_disabled_skills()
|
|
163
|
+
skills = discover_skills()
|
|
164
|
+
enabled = get_skills_enabled()
|
|
165
|
+
|
|
166
|
+
if not skills:
|
|
167
|
+
emit_info("No skills found.")
|
|
168
|
+
emit_info("Create skills in:")
|
|
169
|
+
emit_info(" - ~/.code_puppy/skills/")
|
|
170
|
+
emit_info(" - ./skills/")
|
|
171
|
+
return True
|
|
172
|
+
|
|
173
|
+
emit_info(
|
|
174
|
+
f"\U0001f6e0\ufe0f Skills (integration: {'enabled' if enabled else 'disabled'})"
|
|
175
|
+
)
|
|
176
|
+
emit_info(f"Found {len(skills)} skill(s):\n")
|
|
177
|
+
|
|
178
|
+
for skill in skills:
|
|
179
|
+
metadata = parse_skill_metadata(skill.path)
|
|
180
|
+
if metadata:
|
|
181
|
+
status = (
|
|
182
|
+
"\U0001f534 disabled"
|
|
183
|
+
if metadata.name in disabled_skills
|
|
184
|
+
else "\U0001f7e2 enabled"
|
|
185
|
+
)
|
|
186
|
+
version_str = f" v{metadata.version}" if metadata.version else ""
|
|
187
|
+
author_str = f" by {metadata.author}" if metadata.author else ""
|
|
188
|
+
emit_info(f" {status} {metadata.name}{version_str}{author_str}")
|
|
189
|
+
emit_info(f" {metadata.description}")
|
|
190
|
+
if metadata.tags:
|
|
191
|
+
emit_info(f" tags: {', '.join(metadata.tags)}")
|
|
192
|
+
else:
|
|
193
|
+
status = (
|
|
194
|
+
"\U0001f534 disabled"
|
|
195
|
+
if skill.name in disabled_skills
|
|
196
|
+
else "\U0001f7e2 enabled"
|
|
197
|
+
)
|
|
198
|
+
emit_info(f" {status} {skill.name}")
|
|
199
|
+
emit_info(" (no SKILL.md metadata found)")
|
|
200
|
+
emit_info("")
|
|
201
|
+
return True
|
|
202
|
+
|
|
203
|
+
elif subcommand == "install":
|
|
204
|
+
from code_puppy_core_plugins.agent_skills.skills_install_menu import (
|
|
205
|
+
run_skills_install_menu,
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
run_skills_install_menu()
|
|
209
|
+
return True
|
|
210
|
+
|
|
211
|
+
elif subcommand == "enable":
|
|
212
|
+
set_skills_enabled(True)
|
|
213
|
+
emit_success("\u2705 Skills integration enabled globally")
|
|
214
|
+
return True
|
|
215
|
+
|
|
216
|
+
elif subcommand == "disable":
|
|
217
|
+
set_skills_enabled(False)
|
|
218
|
+
emit_warning("\U0001f534 Skills integration disabled globally")
|
|
219
|
+
return True
|
|
220
|
+
|
|
221
|
+
elif subcommand == "toggle":
|
|
222
|
+
new_state = not get_skills_enabled()
|
|
223
|
+
set_skills_enabled(new_state)
|
|
224
|
+
if new_state:
|
|
225
|
+
emit_success("✅ Skills integration enabled globally")
|
|
226
|
+
else:
|
|
227
|
+
emit_warning("🔴 Skills integration disabled globally")
|
|
228
|
+
return True
|
|
229
|
+
|
|
230
|
+
elif subcommand == "frontmatter":
|
|
231
|
+
# /skills frontmatter [on|off|toggle] (no arg = show state)
|
|
232
|
+
arg = tokens[2].lower() if len(tokens) > 2 else None
|
|
233
|
+
current = get_frontmatter_in_system_prompt()
|
|
234
|
+
|
|
235
|
+
if arg in ("on", "enable", "true"):
|
|
236
|
+
new_state = True
|
|
237
|
+
elif arg in ("off", "disable", "false"):
|
|
238
|
+
new_state = False
|
|
239
|
+
elif arg == "toggle":
|
|
240
|
+
new_state = not current
|
|
241
|
+
elif arg is None:
|
|
242
|
+
emit_info(
|
|
243
|
+
f"Skill frontmatter in system prompt: "
|
|
244
|
+
f"{'🟢 on' if current else '🔴 off'}"
|
|
245
|
+
)
|
|
246
|
+
emit_info("Usage: /skills frontmatter [on|off|toggle]")
|
|
247
|
+
return True
|
|
248
|
+
else:
|
|
249
|
+
emit_error(f"Unknown frontmatter arg: {arg}")
|
|
250
|
+
emit_info("Usage: /skills frontmatter [on|off|toggle]")
|
|
251
|
+
return True
|
|
252
|
+
|
|
253
|
+
set_frontmatter_in_system_prompt(new_state)
|
|
254
|
+
if new_state:
|
|
255
|
+
emit_success(
|
|
256
|
+
"✅ Skill frontmatter will be injected into system prompts"
|
|
257
|
+
)
|
|
258
|
+
else:
|
|
259
|
+
emit_warning(
|
|
260
|
+
"🔴 Skill frontmatter hidden from system prompts "
|
|
261
|
+
"(model can still call activate_skill / list_or_search_skills)"
|
|
262
|
+
)
|
|
263
|
+
return True
|
|
264
|
+
|
|
265
|
+
elif subcommand == "refresh":
|
|
266
|
+
refreshed = refresh_skill_cache()
|
|
267
|
+
valid_skills = [skill for skill in refreshed if skill.has_skill_md]
|
|
268
|
+
emit_success(
|
|
269
|
+
f"🔄 Refreshed skills cache: {len(refreshed)} discovered "
|
|
270
|
+
f"({len(valid_skills)} with SKILL.md)"
|
|
271
|
+
)
|
|
272
|
+
return True
|
|
273
|
+
|
|
274
|
+
elif subcommand == "help":
|
|
275
|
+
emit_info("Available /skills subcommands:")
|
|
276
|
+
emit_info(" /skills list - List all installed skills")
|
|
277
|
+
emit_info(" /skills install - Browse & install from catalog")
|
|
278
|
+
emit_info(" /skills enable - Enable skills integration globally")
|
|
279
|
+
emit_info(" /skills disable - Disable skills integration globally")
|
|
280
|
+
emit_info(" /skills toggle - Toggle skills integration globally")
|
|
281
|
+
emit_info(
|
|
282
|
+
" /skills frontmatter [on|off|toggle] - Toggle skill list injection into system prompt"
|
|
283
|
+
)
|
|
284
|
+
emit_info(" /skills refresh - Refresh skill cache")
|
|
285
|
+
emit_info(" /skills - Open interactive skills menu")
|
|
286
|
+
return True
|
|
287
|
+
|
|
288
|
+
else:
|
|
289
|
+
emit_error(f"Unknown subcommand: {subcommand}")
|
|
290
|
+
emit_info(
|
|
291
|
+
"Usage: /skills [list|install|enable|disable|toggle|frontmatter|refresh|help]"
|
|
292
|
+
)
|
|
293
|
+
return True
|
|
294
|
+
|
|
295
|
+
# No subcommand – launch TUI menu
|
|
296
|
+
show_skills_menu()
|
|
297
|
+
return True
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
# ---------------------------------------------------------------------------
|
|
301
|
+
# Register all callbacks
|
|
302
|
+
# ---------------------------------------------------------------------------
|
|
303
|
+
register_callback("get_model_system_prompt", _inject_skills_into_prompt)
|
|
304
|
+
register_callback("register_tools", _register_skills_tools)
|
|
305
|
+
register_callback("register_skills", _register_skills)
|
|
306
|
+
register_callback("custom_command_help", _skills_command_help)
|
|
307
|
+
register_callback("custom_command", _handle_skills_command)
|
|
308
|
+
|
|
309
|
+
logger.info("Agent Skills plugin loaded")
|