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,158 @@
|
|
|
1
|
+
"""browse_skill_namespace — the on-demand discovery tool.
|
|
2
|
+
|
|
3
|
+
This is the model-agnostic analog of OpenAI's `tool_search` (and
|
|
4
|
+
Anthropic's Tool Search Tool): the model calls it when it needs a
|
|
5
|
+
capability instead of scanning a flat list baked into the system prompt.
|
|
6
|
+
Three modes, one tool, matching the three things a model actually needs
|
|
7
|
+
to do at this scale:
|
|
8
|
+
|
|
9
|
+
browse_skill_namespace() -> list namespaces (directory)
|
|
10
|
+
browse_skill_namespace(namespace="Finance") -> list skills in one namespace
|
|
11
|
+
browse_skill_namespace(query="variance") -> keyword search, all namespaces
|
|
12
|
+
|
|
13
|
+
No model-provider-specific `defer_loading` flag required — the reduction
|
|
14
|
+
in upfront context comes from the `load_prompt` summary block (see
|
|
15
|
+
namespaces.py) being a few lines per namespace instead of one line per
|
|
16
|
+
skill. This tool is just the drill-down mechanism underneath it.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
import asyncio
|
|
22
|
+
from typing import List, Optional
|
|
23
|
+
|
|
24
|
+
from pydantic import BaseModel
|
|
25
|
+
from pydantic_ai import RunContext
|
|
26
|
+
|
|
27
|
+
from .namespaces import build_namespaces
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class NamespaceBrowseOutput(BaseModel):
|
|
31
|
+
"""Uniform output for all three browse_skill_namespace modes."""
|
|
32
|
+
|
|
33
|
+
mode: str # "directory" | "namespace" | "search"
|
|
34
|
+
namespaces: List[str] = [] # populated in "directory" mode
|
|
35
|
+
skills: List[dict] = [] # populated in "namespace"/"search" modes
|
|
36
|
+
total_skills: int = 0
|
|
37
|
+
error: Optional[str] = None
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _skill_matches(skill_haystack: str, terms: List[str]) -> bool:
|
|
41
|
+
return any(term in skill_haystack for term in terms)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _query_terms(query: Optional[str]) -> List[str]:
|
|
45
|
+
"""Split a query into lowercase terms.
|
|
46
|
+
|
|
47
|
+
A blank or whitespace-only query means "no filter", not "filter to
|
|
48
|
+
nothing" -- ``any(term in haystack for term in [])`` is ``False`` for
|
|
49
|
+
every skill, which would otherwise make ``query=""`` or
|
|
50
|
+
``query=" "`` silently return zero results instead of the
|
|
51
|
+
unfiltered set the caller almost certainly intended.
|
|
52
|
+
"""
|
|
53
|
+
if not query or not query.strip():
|
|
54
|
+
return []
|
|
55
|
+
return query.lower().split()
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def register_browse_skill_namespace(agent):
|
|
59
|
+
"""Register the browse_skill_namespace tool on an agent."""
|
|
60
|
+
|
|
61
|
+
@agent.tool
|
|
62
|
+
async def browse_skill_namespace(
|
|
63
|
+
context: RunContext,
|
|
64
|
+
namespace: Optional[str] = None,
|
|
65
|
+
query: Optional[str] = None,
|
|
66
|
+
) -> NamespaceBrowseOutput:
|
|
67
|
+
"""Discover skills without loading all of them into context at once.
|
|
68
|
+
|
|
69
|
+
Call with no arguments first to see the namespace directory (a
|
|
70
|
+
short list of domains + counts). Then either drill into one
|
|
71
|
+
namespace by name, or keyword-search across every namespace at
|
|
72
|
+
once. Call activate_skill(name) on whatever you find.
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
namespace: Exact namespace name to list skills within.
|
|
76
|
+
query: Keyword(s) to search across name/description/tags.
|
|
77
|
+
"""
|
|
78
|
+
# build_namespaces() performs blocking filesystem/frontmatter I/O; explicitly
|
|
79
|
+
# offload it because async pydantic-ai tools aren't auto-threaded.
|
|
80
|
+
try:
|
|
81
|
+
namespaces = await asyncio.to_thread(build_namespaces)
|
|
82
|
+
except Exception as exc: # noqa: BLE001 - surface to the model, don't crash the turn
|
|
83
|
+
return NamespaceBrowseOutput(
|
|
84
|
+
mode="directory",
|
|
85
|
+
error=f"Failed to read skill catalog: {exc}",
|
|
86
|
+
)
|
|
87
|
+
total = sum(len(v) for v in namespaces.values())
|
|
88
|
+
|
|
89
|
+
if not namespaces:
|
|
90
|
+
return NamespaceBrowseOutput(
|
|
91
|
+
mode="directory",
|
|
92
|
+
error="No skills available (skills disabled or none installed).",
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
# Mode 1: directory listing (no args)
|
|
96
|
+
if namespace is None and query is None:
|
|
97
|
+
return NamespaceBrowseOutput(
|
|
98
|
+
mode="directory",
|
|
99
|
+
namespaces=sorted(namespaces.keys(), key=lambda n: -len(namespaces[n])),
|
|
100
|
+
total_skills=total,
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
# Mode 2: drill into a specific namespace
|
|
104
|
+
if namespace is not None:
|
|
105
|
+
matched_ns = next(
|
|
106
|
+
(n for n in namespaces if n.lower() == namespace.lower()), None
|
|
107
|
+
)
|
|
108
|
+
if matched_ns is None:
|
|
109
|
+
return NamespaceBrowseOutput(
|
|
110
|
+
mode="namespace",
|
|
111
|
+
error=(
|
|
112
|
+
f"Namespace '{namespace}' not found. Call "
|
|
113
|
+
"browse_skill_namespace() with no arguments to see "
|
|
114
|
+
"valid namespace names."
|
|
115
|
+
),
|
|
116
|
+
)
|
|
117
|
+
skills = namespaces[matched_ns]
|
|
118
|
+
terms = _query_terms(query)
|
|
119
|
+
if terms:
|
|
120
|
+
skills = [
|
|
121
|
+
s
|
|
122
|
+
for s in skills
|
|
123
|
+
if _skill_matches(
|
|
124
|
+
f"{s.name} {s.description} {' '.join(s.tags)}".lower(),
|
|
125
|
+
terms,
|
|
126
|
+
)
|
|
127
|
+
]
|
|
128
|
+
return NamespaceBrowseOutput(
|
|
129
|
+
mode="namespace",
|
|
130
|
+
skills=[
|
|
131
|
+
{"name": s.name, "description": s.description, "tags": s.tags}
|
|
132
|
+
for s in skills
|
|
133
|
+
],
|
|
134
|
+
total_skills=len(skills),
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
# Mode 3 searches all namespaces; explicit blank query means "no filter",
|
|
138
|
+
# unlike omitted args, which select mode 1's directory listing.
|
|
139
|
+
terms = _query_terms(query)
|
|
140
|
+
results = [
|
|
141
|
+
{
|
|
142
|
+
"name": s.name,
|
|
143
|
+
"description": s.description,
|
|
144
|
+
"tags": s.tags,
|
|
145
|
+
"namespace": ns,
|
|
146
|
+
}
|
|
147
|
+
for ns, skills in namespaces.items()
|
|
148
|
+
for s in skills
|
|
149
|
+
if not terms
|
|
150
|
+
or _skill_matches(
|
|
151
|
+
f"{s.name} {s.description} {' '.join(s.tags)}".lower(), terms
|
|
152
|
+
)
|
|
153
|
+
]
|
|
154
|
+
return NamespaceBrowseOutput(
|
|
155
|
+
mode="search", skills=results, total_skills=len(results)
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
return browse_skill_namespace
|
|
File without changes
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""``--no-tools`` CLI flag (issue #182).
|
|
2
|
+
|
|
3
|
+
Lets wrappers run Code Puppy as a plain text-in/text-out subprocess:
|
|
4
|
+
no tools registered on any agent, no MCP toolsets attached, and no tool
|
|
5
|
+
schemas eating tokens in the request.
|
|
6
|
+
|
|
7
|
+
Implementation is deliberately tiny: the flag just sets the
|
|
8
|
+
``CODE_PUPPY_NO_TOOLS`` env var, and the core tool registry
|
|
9
|
+
(``code_puppy.tools.tools_disabled``) honors it. Wrappers that can't pass
|
|
10
|
+
CLI flags can set the env var directly — same effect, zero magic.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import os
|
|
16
|
+
from typing import Any, Optional
|
|
17
|
+
|
|
18
|
+
from code_puppy.callbacks import register_callback
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _register_cli_args(parser: Any) -> None:
|
|
22
|
+
parser.add_argument(
|
|
23
|
+
"--no-tools",
|
|
24
|
+
action="store_true",
|
|
25
|
+
help=(
|
|
26
|
+
"Disable all agent tools and MCP servers for this run "
|
|
27
|
+
"(pure text-in/text-out; equivalent to CODE_PUPPY_NO_TOOLS=1)"
|
|
28
|
+
),
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _handle_cli_args(args: Any) -> Optional[dict]:
|
|
33
|
+
if getattr(args, "no_tools", False):
|
|
34
|
+
from code_puppy.tools import NO_TOOLS_ENV_VAR
|
|
35
|
+
|
|
36
|
+
os.environ[NO_TOOLS_ENV_VAR] = "1"
|
|
37
|
+
# Never short-circuit startup — this flag only flips the kill-switch.
|
|
38
|
+
return None
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
register_callback("register_cli_args", _register_cli_args)
|
|
42
|
+
register_callback("handle_cli_args", _handle_cli_args)
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"""Helpers for OAuth flows that support terminal paste-back."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
import sys
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
from typing import Optional
|
|
9
|
+
from urllib.parse import parse_qs, urlparse
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass(frozen=True)
|
|
13
|
+
class ParsedOAuthCallback:
|
|
14
|
+
"""Parsed authorization result from a pasted callback URL or code."""
|
|
15
|
+
|
|
16
|
+
code: Optional[str] = None
|
|
17
|
+
state: Optional[str] = None
|
|
18
|
+
error: Optional[str] = None
|
|
19
|
+
error_description: Optional[str] = None
|
|
20
|
+
|
|
21
|
+
@property
|
|
22
|
+
def error_message(self) -> Optional[str]:
|
|
23
|
+
if not self.error:
|
|
24
|
+
return None
|
|
25
|
+
if self.error_description:
|
|
26
|
+
return f"{self.error}: {self.error_description}"
|
|
27
|
+
return self.error
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _first(params: dict[str, list[str]], name: str) -> Optional[str]:
|
|
31
|
+
values = params.get(name)
|
|
32
|
+
if not values:
|
|
33
|
+
return None
|
|
34
|
+
value = values[0].strip()
|
|
35
|
+
return value or None
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _looks_like_query(value: str) -> bool:
|
|
39
|
+
if value.startswith("?"):
|
|
40
|
+
return True
|
|
41
|
+
return "=" in value and (
|
|
42
|
+
"&" in value or value.startswith(("code=", "state=", "error="))
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def parse_oauth_callback_input(raw_input: str) -> ParsedOAuthCallback:
|
|
47
|
+
"""Parse pasted OAuth input into code/state/error fields.
|
|
48
|
+
|
|
49
|
+
Supported inputs include full callback URLs, raw query strings, Claude's
|
|
50
|
+
``code#state`` and ``code state`` console formats, and bare codes.
|
|
51
|
+
"""
|
|
52
|
+
value = raw_input.strip()
|
|
53
|
+
if not value:
|
|
54
|
+
raise ValueError("Authorization code cannot be empty")
|
|
55
|
+
|
|
56
|
+
parsed_url = urlparse(value)
|
|
57
|
+
query = parsed_url.query
|
|
58
|
+
if query or _looks_like_query(value):
|
|
59
|
+
params = parse_qs(query or value.lstrip("?"), keep_blank_values=False)
|
|
60
|
+
result = ParsedOAuthCallback(
|
|
61
|
+
code=_first(params, "code"),
|
|
62
|
+
state=_first(params, "state"),
|
|
63
|
+
error=_first(params, "error"),
|
|
64
|
+
error_description=_first(params, "error_description"),
|
|
65
|
+
)
|
|
66
|
+
if result.code or result.error:
|
|
67
|
+
return result
|
|
68
|
+
raise ValueError("No authorization code found in pasted OAuth input")
|
|
69
|
+
|
|
70
|
+
if "#" in value:
|
|
71
|
+
code, state = value.split("#", 1)
|
|
72
|
+
code = code.strip()
|
|
73
|
+
state = state.strip() or None
|
|
74
|
+
if not code:
|
|
75
|
+
raise ValueError("Authorization code cannot be empty")
|
|
76
|
+
return ParsedOAuthCallback(code=code, state=state)
|
|
77
|
+
|
|
78
|
+
parts = value.split()
|
|
79
|
+
if len(parts) == 2:
|
|
80
|
+
return ParsedOAuthCallback(code=parts[0].strip(), state=parts[1].strip())
|
|
81
|
+
if len(parts) > 2:
|
|
82
|
+
raise ValueError("Pasted OAuth input has too many whitespace-separated parts")
|
|
83
|
+
|
|
84
|
+
return ParsedOAuthCallback(code=value)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def read_available_stdin_line() -> Optional[str]:
|
|
88
|
+
"""Return one stdin line when available without blocking.
|
|
89
|
+
|
|
90
|
+
The OAuth callback server can complete in parallel, so the auth flow must
|
|
91
|
+
not block indefinitely on input. This helper is intentionally POSIX-only;
|
|
92
|
+
Windows callers still retain browser callback behavior and explicit timeout.
|
|
93
|
+
"""
|
|
94
|
+
if os.name == "nt":
|
|
95
|
+
return None
|
|
96
|
+
|
|
97
|
+
try:
|
|
98
|
+
import select
|
|
99
|
+
|
|
100
|
+
readable, _, _ = select.select([sys.stdin], [], [], 0)
|
|
101
|
+
except (OSError, ValueError):
|
|
102
|
+
return None
|
|
103
|
+
|
|
104
|
+
if not readable:
|
|
105
|
+
return None
|
|
106
|
+
|
|
107
|
+
line = sys.stdin.readline()
|
|
108
|
+
if line == "":
|
|
109
|
+
return None
|
|
110
|
+
return line.rstrip("\r\n")
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
"""Small, self-contained HTML pages for browser-based OAuth callbacks."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from html import escape
|
|
6
|
+
from typing import Optional
|
|
7
|
+
|
|
8
|
+
_PAGE_STYLES = """
|
|
9
|
+
:root {
|
|
10
|
+
color-scheme: light dark;
|
|
11
|
+
--bg: #f5f3ef;
|
|
12
|
+
--card: rgba(255, 255, 255, 0.92);
|
|
13
|
+
--border: rgba(28, 25, 23, 0.10);
|
|
14
|
+
--text: #1c1917;
|
|
15
|
+
--muted: #6b645f;
|
|
16
|
+
--success: #16845b;
|
|
17
|
+
--success-soft: #e7f6ef;
|
|
18
|
+
--failure: #c2413a;
|
|
19
|
+
--failure-soft: #fcebea;
|
|
20
|
+
--shadow: 0 24px 70px rgba(41, 37, 36, 0.12);
|
|
21
|
+
}
|
|
22
|
+
* { box-sizing: border-box; }
|
|
23
|
+
body {
|
|
24
|
+
min-height: 100vh;
|
|
25
|
+
margin: 0;
|
|
26
|
+
display: grid;
|
|
27
|
+
place-items: center;
|
|
28
|
+
padding: 24px;
|
|
29
|
+
background:
|
|
30
|
+
radial-gradient(circle at 20% 10%, rgba(249, 115, 22, 0.08), transparent 30%),
|
|
31
|
+
var(--bg);
|
|
32
|
+
color: var(--text);
|
|
33
|
+
font-family: Inter, ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
34
|
+
}
|
|
35
|
+
.card {
|
|
36
|
+
width: min(100%, 480px);
|
|
37
|
+
padding: 40px;
|
|
38
|
+
border: 1px solid var(--border);
|
|
39
|
+
border-radius: 24px;
|
|
40
|
+
background: var(--card);
|
|
41
|
+
box-shadow: var(--shadow);
|
|
42
|
+
text-align: center;
|
|
43
|
+
}
|
|
44
|
+
.mark {
|
|
45
|
+
width: 64px;
|
|
46
|
+
height: 64px;
|
|
47
|
+
margin: 0 auto 24px;
|
|
48
|
+
display: grid;
|
|
49
|
+
place-items: center;
|
|
50
|
+
border-radius: 18px;
|
|
51
|
+
background: #1c1917;
|
|
52
|
+
color: #fff;
|
|
53
|
+
font-size: 30px;
|
|
54
|
+
box-shadow: 0 10px 24px rgba(28, 25, 23, 0.16);
|
|
55
|
+
}
|
|
56
|
+
.eyebrow {
|
|
57
|
+
margin: 0 0 10px;
|
|
58
|
+
color: var(--muted);
|
|
59
|
+
font-size: 13px;
|
|
60
|
+
font-weight: 700;
|
|
61
|
+
letter-spacing: 0.11em;
|
|
62
|
+
text-transform: uppercase;
|
|
63
|
+
}
|
|
64
|
+
h1 {
|
|
65
|
+
margin: 0;
|
|
66
|
+
font-size: clamp(28px, 6vw, 38px);
|
|
67
|
+
line-height: 1.12;
|
|
68
|
+
letter-spacing: -0.035em;
|
|
69
|
+
}
|
|
70
|
+
.message {
|
|
71
|
+
max-width: 370px;
|
|
72
|
+
margin: 16px auto 0;
|
|
73
|
+
color: var(--muted);
|
|
74
|
+
font-size: 16px;
|
|
75
|
+
line-height: 1.6;
|
|
76
|
+
}
|
|
77
|
+
.status {
|
|
78
|
+
display: inline-flex;
|
|
79
|
+
align-items: center;
|
|
80
|
+
gap: 8px;
|
|
81
|
+
margin-top: 28px;
|
|
82
|
+
padding: 9px 13px;
|
|
83
|
+
border-radius: 999px;
|
|
84
|
+
font-size: 13px;
|
|
85
|
+
font-weight: 700;
|
|
86
|
+
}
|
|
87
|
+
.status::before {
|
|
88
|
+
content: "";
|
|
89
|
+
width: 8px;
|
|
90
|
+
height: 8px;
|
|
91
|
+
border-radius: 50%;
|
|
92
|
+
background: currentColor;
|
|
93
|
+
}
|
|
94
|
+
.success .status { color: var(--success); background: var(--success-soft); }
|
|
95
|
+
.failure .status { color: var(--failure); background: var(--failure-soft); }
|
|
96
|
+
.hint {
|
|
97
|
+
margin: 24px 0 0;
|
|
98
|
+
color: var(--muted);
|
|
99
|
+
font-size: 13px;
|
|
100
|
+
}
|
|
101
|
+
@media (prefers-color-scheme: dark) {
|
|
102
|
+
:root {
|
|
103
|
+
--bg: #121110;
|
|
104
|
+
--card: rgba(29, 27, 25, 0.94);
|
|
105
|
+
--border: rgba(255, 255, 255, 0.09);
|
|
106
|
+
--text: #f7f5f2;
|
|
107
|
+
--muted: #aaa39d;
|
|
108
|
+
--success: #73d5ad;
|
|
109
|
+
--success-soft: rgba(22, 132, 91, 0.18);
|
|
110
|
+
--failure: #f19a94;
|
|
111
|
+
--failure-soft: rgba(194, 65, 58, 0.18);
|
|
112
|
+
--shadow: 0 24px 70px rgba(0, 0, 0, 0.34);
|
|
113
|
+
}
|
|
114
|
+
.mark { background: #f7f5f2; color: #1c1917; }
|
|
115
|
+
}
|
|
116
|
+
@media (max-width: 520px) {
|
|
117
|
+
.card { padding: 32px 24px; border-radius: 20px; }
|
|
118
|
+
}
|
|
119
|
+
"""
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def oauth_success_html(service_name: str, extra_message: Optional[str] = None) -> str:
|
|
123
|
+
"""Return a restrained success page for an OAuth callback."""
|
|
124
|
+
service = _clean(service_name, "OAuth")
|
|
125
|
+
message = _clean(
|
|
126
|
+
extra_message,
|
|
127
|
+
"Authentication is complete. You can return to Code Puppy.",
|
|
128
|
+
)
|
|
129
|
+
return _render_page(
|
|
130
|
+
service=service,
|
|
131
|
+
state="success",
|
|
132
|
+
title="You're connected",
|
|
133
|
+
message=message,
|
|
134
|
+
status="Authentication complete",
|
|
135
|
+
hint="This window can be closed safely.",
|
|
136
|
+
auto_close=True,
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def oauth_failure_html(service_name: str, reason: str) -> str:
|
|
141
|
+
"""Return a clear, low-drama failure page for an OAuth callback."""
|
|
142
|
+
service = _clean(service_name, "OAuth")
|
|
143
|
+
message = _clean(reason, "Authentication could not be completed.")
|
|
144
|
+
return _render_page(
|
|
145
|
+
service=service,
|
|
146
|
+
state="failure",
|
|
147
|
+
title="Couldn't connect",
|
|
148
|
+
message=message,
|
|
149
|
+
status="Authentication incomplete",
|
|
150
|
+
hint="Return to Code Puppy and try signing in again.",
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def _clean(value: Optional[str], fallback: str) -> str:
|
|
155
|
+
"""Normalize and HTML-escape dynamic page content."""
|
|
156
|
+
normalized = value.strip() if value else fallback
|
|
157
|
+
return escape(normalized or fallback)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def _render_page(
|
|
161
|
+
*,
|
|
162
|
+
service: str,
|
|
163
|
+
state: str,
|
|
164
|
+
title: str,
|
|
165
|
+
message: str,
|
|
166
|
+
status: str,
|
|
167
|
+
hint: str,
|
|
168
|
+
auto_close: bool = False,
|
|
169
|
+
) -> str:
|
|
170
|
+
"""Build a complete OAuth result page without remote assets."""
|
|
171
|
+
close_script = (
|
|
172
|
+
"<script>setTimeout(() => window.close(), 3500);</script>" if auto_close else ""
|
|
173
|
+
)
|
|
174
|
+
return f"""<!doctype html>
|
|
175
|
+
<html lang="en">
|
|
176
|
+
<head>
|
|
177
|
+
<meta charset="utf-8">
|
|
178
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
179
|
+
<meta name="robots" content="noindex, nofollow">
|
|
180
|
+
<title>{service} authentication</title>
|
|
181
|
+
<style>{_PAGE_STYLES}</style>
|
|
182
|
+
</head>
|
|
183
|
+
<body>
|
|
184
|
+
<main class="card {state}">
|
|
185
|
+
<div class="mark" aria-hidden="true">CP</div>
|
|
186
|
+
<p class="eyebrow">Code Puppy · {service}</p>
|
|
187
|
+
<h1>{title}</h1>
|
|
188
|
+
<p class="message">{message}</p>
|
|
189
|
+
<div class="status" role="status">{status}</div>
|
|
190
|
+
<p class="hint">{hint}</p>
|
|
191
|
+
</main>
|
|
192
|
+
{close_script}
|
|
193
|
+
</body>
|
|
194
|
+
</html>"""
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Obsidian Agent
|
|
2
|
+
|
|
3
|
+
The Obsidian Agent adds a specialized Code Puppy agent for working with Obsidian vaults through the official `obsidian` CLI.
|
|
4
|
+
|
|
5
|
+
## What it does
|
|
6
|
+
|
|
7
|
+
- Discovers vaults, notes, folders, links, tags, tasks, templates, and related Obsidian state.
|
|
8
|
+
- Uses the Obsidian CLI for vault-aware operations instead of blindly editing files.
|
|
9
|
+
- Follows a read-before-write workflow for note changes.
|
|
10
|
+
- Requires explicit confirmation for destructive, broad, or hard-to-reverse operations.
|
|
11
|
+
- Helps troubleshoot common CLI setup issues.
|
|
12
|
+
|
|
13
|
+
## Requirements
|
|
14
|
+
|
|
15
|
+
- Obsidian desktop 1.12.7 or newer.
|
|
16
|
+
- Obsidian's command line interface enabled in Settings → General.
|
|
17
|
+
- The Obsidian desktop app running, or available to be launched by the CLI.
|
|
18
|
+
- The `obsidian` command available on `PATH`.
|
|
19
|
+
|
|
20
|
+
Useful checks:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
which obsidian
|
|
24
|
+
obsidian version
|
|
25
|
+
obsidian help
|
|
26
|
+
obsidian vaults total verbose
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Usage
|
|
30
|
+
|
|
31
|
+
Switch to the agent from Code Puppy and ask for an Obsidian task. Include a vault name or vault-relative path when relevant.
|
|
32
|
+
|
|
33
|
+
Examples:
|
|
34
|
+
|
|
35
|
+
- "Find notes about release planning in my work vault."
|
|
36
|
+
- "Create a meeting note from my weekly meeting template."
|
|
37
|
+
- "Append this task to today's daily note."
|
|
38
|
+
- "Show unresolved links and propose a cleanup plan."
|
|
39
|
+
|
|
40
|
+
For broad updates, the agent should present a plan and ask for confirmation before making changes. Tiny bureaucracy, but the useful kind.
|
|
41
|
+
|
|
42
|
+
## Safety notes
|
|
43
|
+
|
|
44
|
+
The agent intentionally avoids personal defaults. It does not include any user-specific vault names, local paths, or private note structure.
|
|
45
|
+
|
|
46
|
+
It treats these as confirmation-required operations:
|
|
47
|
+
|
|
48
|
+
- Permanent deletes, moves, and renames.
|
|
49
|
+
- History or sync restores.
|
|
50
|
+
- Publish changes.
|
|
51
|
+
- Plugin, theme, snippet, sync, reload, restart, and developer/debug commands.
|
|
52
|
+
- Arbitrary JavaScript evaluation.
|