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,238 @@
|
|
|
1
|
+
# Azure AI Foundry Plugin for Code Puppy
|
|
2
|
+
|
|
3
|
+
This plugin enables Code Puppy to use Anthropic Claude models hosted on
|
|
4
|
+
Microsoft Azure AI Foundry with Azure AD (Entra ID) authentication.
|
|
5
|
+
|
|
6
|
+
## Overview
|
|
7
|
+
|
|
8
|
+
Azure AI Foundry provides enterprise-grade hosting of Anthropic Claude models
|
|
9
|
+
within the Microsoft Azure cloud. This plugin uses your existing Azure CLI
|
|
10
|
+
credentials (`az login`) to authenticate, eliminating the need for API keys.
|
|
11
|
+
|
|
12
|
+
## Supported Models
|
|
13
|
+
|
|
14
|
+
| Model | Context Length | Deployment Name (Default) |
|
|
15
|
+
|-------|----------------|---------------------------|
|
|
16
|
+
| Claude Opus 4.6 | 1M tokens | `claude-opus-4-6` |
|
|
17
|
+
| Claude Sonnet 4.6 | 1M tokens | `claude-sonnet-4-6` |
|
|
18
|
+
| Claude Haiku 4.5 | 200K tokens | `claude-haiku-4-5` |
|
|
19
|
+
|
|
20
|
+
Deployment names are user-configurable during setup.
|
|
21
|
+
|
|
22
|
+
## Prerequisites
|
|
23
|
+
|
|
24
|
+
1. **Azure subscription** with access to Azure AI Foundry
|
|
25
|
+
2. **Azure CLI** installed and authenticated (`az login`)
|
|
26
|
+
3. **Claude model deployments** provisioned in your Azure AI Foundry resource
|
|
27
|
+
4. **Python packages**: `azure-identity>=1.15.0` (installed with Code Puppy)
|
|
28
|
+
|
|
29
|
+
## Quick Start
|
|
30
|
+
|
|
31
|
+
### 1. Authenticate with Azure
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
az login
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### 2. Set Your Resource Name
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
export ANTHROPIC_FOUNDRY_RESOURCE=your-resource-name
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### 3. Run Interactive Setup
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
pup
|
|
47
|
+
/foundry-setup
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
The wizard will guide you through configuring your model deployments.
|
|
51
|
+
|
|
52
|
+
### 4. Start Using Foundry Models
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
/model foundry-claude-opus
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Configuration
|
|
59
|
+
|
|
60
|
+
### Environment Variables
|
|
61
|
+
|
|
62
|
+
| Variable | Description | Required |
|
|
63
|
+
|----------|-------------|----------|
|
|
64
|
+
| `ANTHROPIC_FOUNDRY_RESOURCE` | Your Azure AI Foundry resource name | Yes |
|
|
65
|
+
| `ANTHROPIC_FOUNDRY_BASE_URL` | Override the base URL (optional) | No |
|
|
66
|
+
|
|
67
|
+
### Model Configuration
|
|
68
|
+
|
|
69
|
+
Models are stored in `~/.code_puppy/extra_models.json`:
|
|
70
|
+
|
|
71
|
+
```json
|
|
72
|
+
{
|
|
73
|
+
"foundry-claude-opus": {
|
|
74
|
+
"type": "azure_foundry",
|
|
75
|
+
"name": "it-entra-claude-opus-4-6[1m]",
|
|
76
|
+
"foundry_resource": "$ANTHROPIC_FOUNDRY_RESOURCE",
|
|
77
|
+
"context_length": 1000000,
|
|
78
|
+
"supported_settings": ["temperature", "extended_thinking", "effort"]
|
|
79
|
+
},
|
|
80
|
+
"foundry-claude-sonnet": {
|
|
81
|
+
"type": "azure_foundry",
|
|
82
|
+
"name": "it-entra-claude-sonnet-4-6[1m]",
|
|
83
|
+
"foundry_resource": "$ANTHROPIC_FOUNDRY_RESOURCE",
|
|
84
|
+
"context_length": 1000000,
|
|
85
|
+
"supported_settings": ["temperature", "interleaved_thinking", "thinking_budget"]
|
|
86
|
+
},
|
|
87
|
+
"foundry-claude-haiku": {
|
|
88
|
+
"type": "azure_foundry",
|
|
89
|
+
"name": "it-entra-claude-haiku-4-5",
|
|
90
|
+
"foundry_resource": "$ANTHROPIC_FOUNDRY_RESOURCE",
|
|
91
|
+
"context_length": 200000,
|
|
92
|
+
"supported_settings": ["temperature", "interleaved_thinking", "thinking_budget"]
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
**Configuration Fields:**
|
|
98
|
+
|
|
99
|
+
- `type`: Must be `"azure_foundry"` to route to this plugin
|
|
100
|
+
- `name`: Your Azure deployment name (e.g., `it-entra-claude-opus-4-6`)
|
|
101
|
+
- `foundry_resource`: Resource name (supports `$ENV_VAR` syntax)
|
|
102
|
+
- `context_length`: Model context window in tokens
|
|
103
|
+
- `supported_settings`: List of supported model settings
|
|
104
|
+
|
|
105
|
+
## Model Settings by Tier
|
|
106
|
+
|
|
107
|
+
### Opus 4.6 Models
|
|
108
|
+
- `temperature`: Temperature for sampling (0-1)
|
|
109
|
+
- `extended_thinking`: Enable thinking (defaults to "adaptive")
|
|
110
|
+
- `effort`: Thinking effort level ("low", "medium", "high")
|
|
111
|
+
|
|
112
|
+
### Sonnet & Haiku Models
|
|
113
|
+
- `temperature`: Temperature for sampling (0-1)
|
|
114
|
+
- `interleaved_thinking`: Enable interleaved thinking (boolean)
|
|
115
|
+
- `thinking_budget`: Maximum tokens for internal reasoning
|
|
116
|
+
|
|
117
|
+
## Context Window Configuration
|
|
118
|
+
|
|
119
|
+
Deployment names can include a context window suffix following the Claude Code format:
|
|
120
|
+
- `[1m]` - 1 million tokens
|
|
121
|
+
- `[2m]` - 2 million tokens
|
|
122
|
+
- `[200k]` - 200 thousand tokens
|
|
123
|
+
- `[500k]` - 500 thousand tokens
|
|
124
|
+
|
|
125
|
+
When you specify a deployment name with a context suffix (e.g., `it-entra-claude-opus-4-6[1m]`):
|
|
126
|
+
1. The suffix is **automatically stripped** before sending to Azure
|
|
127
|
+
2. The `context_length` is set based on the parsed suffix
|
|
128
|
+
|
|
129
|
+
**Example:**
|
|
130
|
+
|
|
131
|
+
During `/foundry-setup`, if you enter:
|
|
132
|
+
```
|
|
133
|
+
Opus deployment name: it-entra-claude-opus-4-6[1m]
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
The saved configuration will have:
|
|
137
|
+
- `name`: `it-entra-claude-opus-4-6` (suffix stripped)
|
|
138
|
+
- `context_length`: `1000000` (parsed from `[1m]`)
|
|
139
|
+
|
|
140
|
+
This is useful when your Azure deployment names don't include the context indicator,
|
|
141
|
+
but you want to configure the context length.
|
|
142
|
+
|
|
143
|
+
## Slash Commands
|
|
144
|
+
|
|
145
|
+
| Command | Description |
|
|
146
|
+
|---------|-------------|
|
|
147
|
+
| `/foundry-status` | Check Azure AD authentication status and configured models |
|
|
148
|
+
| `/foundry-setup` | Interactive wizard to configure Foundry models |
|
|
149
|
+
| `/foundry-remove` | Remove all Foundry model configurations |
|
|
150
|
+
|
|
151
|
+
### Example: /foundry-status
|
|
152
|
+
|
|
153
|
+
```
|
|
154
|
+
Azure AI Foundry Status
|
|
155
|
+
========================================
|
|
156
|
+
Authentication: Valid (expires in 45 minutes)
|
|
157
|
+
Logged in as: user@company.com
|
|
158
|
+
|
|
159
|
+
Foundry Resource: my-foundry-resource
|
|
160
|
+
|
|
161
|
+
Configured Models (3):
|
|
162
|
+
- foundry-claude-opus: it-entra-claude-opus-4-6[1m]
|
|
163
|
+
- foundry-claude-sonnet: it-entra-claude-sonnet-4-6[1m]
|
|
164
|
+
- foundry-claude-haiku: it-entra-claude-haiku-4-5
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## How It Works
|
|
168
|
+
|
|
169
|
+
1. **Token Acquisition**: Uses `AzureCliCredential` from `azure-identity` to
|
|
170
|
+
obtain tokens from your `az login` session
|
|
171
|
+
|
|
172
|
+
2. **Token Refresh**: The `get_bearer_token_provider` function handles automatic
|
|
173
|
+
token refresh before expiry
|
|
174
|
+
|
|
175
|
+
3. **API Calls**: Creates an `AsyncAnthropicFoundry` client that uses the native
|
|
176
|
+
Anthropic Messages API (not OpenAI format)
|
|
177
|
+
|
|
178
|
+
4. **Integration**: Wraps the client in pydantic-ai's `AnthropicModel` for
|
|
179
|
+
seamless integration with Code Puppy's agent system
|
|
180
|
+
|
|
181
|
+
## Troubleshooting
|
|
182
|
+
|
|
183
|
+
### "CredentialUnavailableError" or "Not authenticated"
|
|
184
|
+
|
|
185
|
+
Run `az login` to authenticate with Azure:
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
az login
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### "Resource not found" or "404 errors"
|
|
192
|
+
|
|
193
|
+
1. Verify `ANTHROPIC_FOUNDRY_RESOURCE` is set correctly
|
|
194
|
+
2. Check that your model deployments exist in Azure AI Foundry
|
|
195
|
+
3. Ensure the deployment names match your configuration
|
|
196
|
+
|
|
197
|
+
### Token Expiry
|
|
198
|
+
|
|
199
|
+
Tokens are automatically refreshed by the Azure Identity library. If you
|
|
200
|
+
encounter issues, try:
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
az account get-access-token --resource https://cognitiveservices.azure.com
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Model Not Found
|
|
207
|
+
|
|
208
|
+
After running `/foundry-setup`, verify configuration with `/foundry-status`.
|
|
209
|
+
Check that deployment names match exactly (case-sensitive).
|
|
210
|
+
|
|
211
|
+
## Architecture
|
|
212
|
+
|
|
213
|
+
```
|
|
214
|
+
code_puppy/plugins/azure_foundry/
|
|
215
|
+
├── __init__.py # Package marker and version
|
|
216
|
+
├── config.py # Constants and configuration helpers
|
|
217
|
+
├── token.py # Azure AD token provider
|
|
218
|
+
├── utils.py # Configuration file utilities
|
|
219
|
+
└── register_callbacks.py # Plugin callbacks and model handler
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## Security Notes
|
|
223
|
+
|
|
224
|
+
- **No API keys stored**: Authentication uses Azure AD tokens only
|
|
225
|
+
- **Token caching**: Managed by Azure CLI, not stored by this plugin
|
|
226
|
+
- **Credential scope**: Limited to `https://cognitiveservices.azure.com/.default`
|
|
227
|
+
|
|
228
|
+
## Contributing
|
|
229
|
+
|
|
230
|
+
This plugin follows Code Puppy's plugin architecture. Key callbacks:
|
|
231
|
+
|
|
232
|
+
- `register_model_type`: Registers `azure_foundry` type handler
|
|
233
|
+
- `custom_command`: Handles `/foundry-*` slash commands
|
|
234
|
+
- `custom_command_help`: Provides help text for commands
|
|
235
|
+
|
|
236
|
+
## License
|
|
237
|
+
|
|
238
|
+
Same as Code Puppy (see repository LICENSE file).
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""Azure AI Foundry Plugin for Code Puppy.
|
|
2
|
+
|
|
3
|
+
This plugin enables Code Puppy to use Anthropic Claude models hosted on
|
|
4
|
+
Microsoft Azure AI Foundry with Azure AD (Entra ID) authentication.
|
|
5
|
+
|
|
6
|
+
The plugin uses the `az login` credentials from the Azure CLI to authenticate,
|
|
7
|
+
eliminating the need for API keys.
|
|
8
|
+
|
|
9
|
+
Supported models:
|
|
10
|
+
- Claude Opus 4.6 (1M context)
|
|
11
|
+
- Claude Sonnet 4.6 (1M context)
|
|
12
|
+
- Claude Haiku 4.5 (200K context)
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
__version__ = "0.1.0"
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"""Configuration constants for the Azure AI Foundry plugin.
|
|
2
|
+
|
|
3
|
+
This module defines constants used throughout the plugin for Azure AD
|
|
4
|
+
authentication and model configuration.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import os
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
13
|
+
from code_puppy.config import DATA_DIR
|
|
14
|
+
|
|
15
|
+
# Azure AD scope for Cognitive Services (used for token acquisition)
|
|
16
|
+
# This scope is required for authenticating with Azure AI Foundry
|
|
17
|
+
AZURE_COGNITIVE_SCOPE = "https://cognitiveservices.azure.com/.default"
|
|
18
|
+
|
|
19
|
+
# Token refresh buffer in seconds (refresh 5 minutes before expiry)
|
|
20
|
+
TOKEN_REFRESH_BUFFER = 300
|
|
21
|
+
|
|
22
|
+
# Default context lengths for different model tiers
|
|
23
|
+
DEFAULT_CONTEXT_LENGTHS: dict[str, int] = {
|
|
24
|
+
"opus": 1000000, # 1M tokens for Opus models
|
|
25
|
+
"sonnet": 1000000, # 1M tokens for Sonnet models
|
|
26
|
+
"haiku": 200000, # 200K tokens for Haiku models
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
# Context lengths for OpenAI models (Azure doesn't expose this in the catalog API).
|
|
30
|
+
# Prefixes are matched longest-first against the model name.
|
|
31
|
+
OPENAI_CONTEXT_LENGTHS: dict[str, int] = {
|
|
32
|
+
"gpt-5.4": 1000000,
|
|
33
|
+
"gpt-5.4-mini": 1000000,
|
|
34
|
+
"gpt-5.3-codex": 1000000,
|
|
35
|
+
"gpt-5.3": 1000000,
|
|
36
|
+
"gpt-5.2-codex": 1000000,
|
|
37
|
+
"gpt-5.2": 1000000,
|
|
38
|
+
"gpt-5.1-codex-max": 1000000,
|
|
39
|
+
"gpt-5.1-codex-mini": 1000000,
|
|
40
|
+
"gpt-5.1-codex": 1000000,
|
|
41
|
+
"gpt-5.1": 1000000,
|
|
42
|
+
"gpt-5-codex": 1000000,
|
|
43
|
+
"gpt-5": 1000000,
|
|
44
|
+
"gpt-4.1": 1000000,
|
|
45
|
+
"gpt-4.1-mini": 1000000,
|
|
46
|
+
"gpt-4.1-nano": 1000000,
|
|
47
|
+
"o4-mini": 200000,
|
|
48
|
+
"o3": 200000,
|
|
49
|
+
"o3-mini": 200000,
|
|
50
|
+
"o1": 200000,
|
|
51
|
+
"o1-mini": 128000,
|
|
52
|
+
"codex-mini": 200000,
|
|
53
|
+
}
|
|
54
|
+
DEFAULT_OPENAI_CONTEXT_LENGTH = 128000
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def get_openai_context_length(model_name: str) -> int:
|
|
58
|
+
"""Look up the context length for an OpenAI model by name.
|
|
59
|
+
|
|
60
|
+
Matches the longest prefix first so 'gpt-5.4-mini' matches before 'gpt-5.4'.
|
|
61
|
+
Falls back to DEFAULT_OPENAI_CONTEXT_LENGTH if no match.
|
|
62
|
+
"""
|
|
63
|
+
for prefix in sorted(OPENAI_CONTEXT_LENGTHS, key=len, reverse=True):
|
|
64
|
+
if model_name.startswith(prefix):
|
|
65
|
+
return OPENAI_CONTEXT_LENGTHS[prefix]
|
|
66
|
+
return DEFAULT_OPENAI_CONTEXT_LENGTH
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
# Default deployment name patterns (can be overridden by user)
|
|
70
|
+
DEFAULT_DEPLOYMENT_NAMES: dict[str, str] = {
|
|
71
|
+
"opus": "claude-opus-4-6",
|
|
72
|
+
"sonnet": "claude-sonnet-4-6",
|
|
73
|
+
"haiku": "claude-haiku-4-5",
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
# Environment variable names
|
|
77
|
+
ENV_FOUNDRY_RESOURCE = "ANTHROPIC_FOUNDRY_RESOURCE"
|
|
78
|
+
ENV_FOUNDRY_BASE_URL = "ANTHROPIC_FOUNDRY_BASE_URL"
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def get_foundry_resource() -> str | None:
|
|
82
|
+
"""Get the Azure Foundry resource name from environment.
|
|
83
|
+
|
|
84
|
+
Returns:
|
|
85
|
+
The resource name if set, None otherwise.
|
|
86
|
+
"""
|
|
87
|
+
return os.environ.get(ENV_FOUNDRY_RESOURCE)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def get_foundry_base_url() -> str | None:
|
|
91
|
+
"""Get the Azure Foundry base URL from environment.
|
|
92
|
+
|
|
93
|
+
If ANTHROPIC_FOUNDRY_BASE_URL is set, use it directly.
|
|
94
|
+
Otherwise, construct from ANTHROPIC_FOUNDRY_RESOURCE.
|
|
95
|
+
|
|
96
|
+
Returns:
|
|
97
|
+
The base URL if determinable, None otherwise.
|
|
98
|
+
"""
|
|
99
|
+
base_url = os.environ.get(ENV_FOUNDRY_BASE_URL)
|
|
100
|
+
if base_url:
|
|
101
|
+
return base_url
|
|
102
|
+
|
|
103
|
+
resource = get_foundry_resource()
|
|
104
|
+
if resource:
|
|
105
|
+
return f"https://{resource}.services.ai.azure.com/anthropic/v1"
|
|
106
|
+
|
|
107
|
+
return None
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def get_extra_models_path() -> Path:
|
|
111
|
+
"""Get the path to the extra_models.json file.
|
|
112
|
+
|
|
113
|
+
Returns:
|
|
114
|
+
Path to the extra models configuration file.
|
|
115
|
+
"""
|
|
116
|
+
return Path(DATA_DIR) / "extra_models.json"
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
# Plugin configuration for model creation
|
|
120
|
+
AZURE_FOUNDRY_CONFIG: dict[str, Any] = {
|
|
121
|
+
"scope": AZURE_COGNITIVE_SCOPE,
|
|
122
|
+
"token_refresh_buffer": TOKEN_REFRESH_BUFFER,
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
# Per-tier supported_settings (see build_foundry_model_config()):
|
|
126
|
+
# Opus 4.6 -> [temperature, extended_thinking, effort]; Sonnet/Haiku -> [temperature, interleaved_thinking, thinking_budget]
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
"""Azure AI Services deployment discovery.
|
|
2
|
+
|
|
3
|
+
Queries the Azure Management API to find AI Services accounts and
|
|
4
|
+
list their model deployments. Works with any AIServices account
|
|
5
|
+
hosting Anthropic, OpenAI, or other model formats.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import logging
|
|
11
|
+
from dataclasses import dataclass
|
|
12
|
+
from typing import Any
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
AZURE_MANAGEMENT_SCOPE = "https://management.azure.com/.default"
|
|
17
|
+
MANAGEMENT_BASE = "https://management.azure.com"
|
|
18
|
+
RESOURCE_API_VERSION = "2021-04-01"
|
|
19
|
+
DEPLOYMENT_API_VERSION = "2024-10-01"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@dataclass
|
|
23
|
+
class AzureAccount:
|
|
24
|
+
"""Discovered Azure AI Services account."""
|
|
25
|
+
|
|
26
|
+
resource_id: str
|
|
27
|
+
name: str
|
|
28
|
+
location: str
|
|
29
|
+
resource_group: str
|
|
30
|
+
subscription_id: str
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@dataclass
|
|
34
|
+
class AzureDeployment:
|
|
35
|
+
"""Discovered model deployment on an Azure AI Services account."""
|
|
36
|
+
|
|
37
|
+
name: str
|
|
38
|
+
model_name: str
|
|
39
|
+
model_format: str # "Anthropic", "OpenAI", etc.
|
|
40
|
+
model_version: str
|
|
41
|
+
provisioning_state: str
|
|
42
|
+
sku_name: str
|
|
43
|
+
capacity: int
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _get_management_token() -> str | None:
|
|
47
|
+
"""Get a token for the Azure Management API using az login credentials.
|
|
48
|
+
|
|
49
|
+
Returns:
|
|
50
|
+
Bearer token string, or None if auth fails.
|
|
51
|
+
"""
|
|
52
|
+
try:
|
|
53
|
+
from azure.identity import AzureCliCredential
|
|
54
|
+
|
|
55
|
+
credential = AzureCliCredential()
|
|
56
|
+
token = credential.get_token(AZURE_MANAGEMENT_SCOPE)
|
|
57
|
+
return token.token
|
|
58
|
+
except Exception as e:
|
|
59
|
+
logger.warning("Failed to get management token: %s", e)
|
|
60
|
+
return None
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _management_get(token: str, url: str) -> dict[str, Any] | None:
|
|
64
|
+
"""Make a GET request to the Azure Management API.
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
token: Bearer token for authentication.
|
|
68
|
+
url: Full URL to GET.
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
Parsed JSON response, or None on error.
|
|
72
|
+
"""
|
|
73
|
+
try:
|
|
74
|
+
import httpx
|
|
75
|
+
|
|
76
|
+
resp = httpx.get(
|
|
77
|
+
url,
|
|
78
|
+
headers={"Authorization": f"Bearer {token}"},
|
|
79
|
+
timeout=30,
|
|
80
|
+
)
|
|
81
|
+
if resp.status_code == 200:
|
|
82
|
+
return resp.json()
|
|
83
|
+
logger.warning("Management API %s returned %d", url, resp.status_code)
|
|
84
|
+
return None
|
|
85
|
+
except Exception as e:
|
|
86
|
+
logger.warning("Management API request failed: %s", e)
|
|
87
|
+
return None
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def find_account(resource_name: str) -> AzureAccount | None:
|
|
91
|
+
"""Find an Azure AI Services account by name across all accessible subscriptions.
|
|
92
|
+
|
|
93
|
+
Args:
|
|
94
|
+
resource_name: The account name to search for.
|
|
95
|
+
|
|
96
|
+
Returns:
|
|
97
|
+
AzureAccount if found, None otherwise.
|
|
98
|
+
"""
|
|
99
|
+
token = _get_management_token()
|
|
100
|
+
if not token:
|
|
101
|
+
return None
|
|
102
|
+
|
|
103
|
+
# List subscriptions
|
|
104
|
+
subs_url = f"{MANAGEMENT_BASE}/subscriptions?api-version=2022-12-01"
|
|
105
|
+
subs_resp = _management_get(token, subs_url)
|
|
106
|
+
if not subs_resp:
|
|
107
|
+
return None
|
|
108
|
+
|
|
109
|
+
subscriptions = subs_resp.get("value", [])
|
|
110
|
+
|
|
111
|
+
for sub in subscriptions:
|
|
112
|
+
sub_id = sub.get("subscriptionId", "")
|
|
113
|
+
if sub.get("state") != "Enabled":
|
|
114
|
+
continue
|
|
115
|
+
|
|
116
|
+
# Search for the resource by name and type
|
|
117
|
+
filter_str = (
|
|
118
|
+
f"name eq '{resource_name}' and "
|
|
119
|
+
f"resourceType eq 'Microsoft.CognitiveServices/accounts'"
|
|
120
|
+
)
|
|
121
|
+
resources_url = (
|
|
122
|
+
f"{MANAGEMENT_BASE}/subscriptions/{sub_id}/resources"
|
|
123
|
+
f"?$filter={filter_str}&api-version={RESOURCE_API_VERSION}"
|
|
124
|
+
)
|
|
125
|
+
resources_resp = _management_get(token, resources_url)
|
|
126
|
+
if not resources_resp:
|
|
127
|
+
continue
|
|
128
|
+
|
|
129
|
+
for resource in resources_resp.get("value", []):
|
|
130
|
+
rid = resource.get("id", "")
|
|
131
|
+
parts = rid.split("/")
|
|
132
|
+
# /subscriptions/{sub}/resourceGroups/{rg}/providers/.../accounts/{name}
|
|
133
|
+
rg_idx = next(
|
|
134
|
+
(i for i, p in enumerate(parts) if p.lower() == "resourcegroups"),
|
|
135
|
+
None,
|
|
136
|
+
)
|
|
137
|
+
rg = parts[rg_idx + 1] if rg_idx is not None else ""
|
|
138
|
+
|
|
139
|
+
return AzureAccount(
|
|
140
|
+
resource_id=rid,
|
|
141
|
+
name=resource_name,
|
|
142
|
+
location=resource.get("location", ""),
|
|
143
|
+
resource_group=rg,
|
|
144
|
+
subscription_id=sub_id,
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
return None
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def list_deployments(account: AzureAccount) -> list[AzureDeployment]:
|
|
151
|
+
"""List all model deployments on an Azure AI Services account.
|
|
152
|
+
|
|
153
|
+
Args:
|
|
154
|
+
account: The account to query.
|
|
155
|
+
|
|
156
|
+
Returns:
|
|
157
|
+
List of deployments (all states, caller filters as needed).
|
|
158
|
+
"""
|
|
159
|
+
token = _get_management_token()
|
|
160
|
+
if not token:
|
|
161
|
+
return []
|
|
162
|
+
|
|
163
|
+
url = (
|
|
164
|
+
f"{MANAGEMENT_BASE}{account.resource_id}"
|
|
165
|
+
f"/deployments?api-version={DEPLOYMENT_API_VERSION}"
|
|
166
|
+
)
|
|
167
|
+
resp = _management_get(token, url)
|
|
168
|
+
if not resp:
|
|
169
|
+
return []
|
|
170
|
+
|
|
171
|
+
deployments = []
|
|
172
|
+
for d in resp.get("value", []):
|
|
173
|
+
props = d.get("properties", {})
|
|
174
|
+
model = props.get("model", {})
|
|
175
|
+
sku = d.get("sku", {})
|
|
176
|
+
|
|
177
|
+
deployments.append(
|
|
178
|
+
AzureDeployment(
|
|
179
|
+
name=d.get("name", ""),
|
|
180
|
+
model_name=model.get("name", ""),
|
|
181
|
+
model_format=model.get("format", ""),
|
|
182
|
+
model_version=model.get("version", ""),
|
|
183
|
+
provisioning_state=props.get("provisioningState", ""),
|
|
184
|
+
sku_name=sku.get("name", ""),
|
|
185
|
+
capacity=sku.get("capacity", 0),
|
|
186
|
+
)
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
return deployments
|