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,165 @@
|
|
|
1
|
+
"""Register callbacks for the ``wide_completion_menu`` plugin.
|
|
2
|
+
|
|
3
|
+
Hooks:
|
|
4
|
+
|
|
5
|
+
* ``startup`` — monkey-patches prompt_toolkit's completion menu width so the
|
|
6
|
+
scrollbar anchors to the right edge of the terminal rather than the right
|
|
7
|
+
edge of the menu content.
|
|
8
|
+
* ``custom_command`` / ``custom_command_help`` — exposes ``/widemenu`` to
|
|
9
|
+
toggle the effect at runtime without restarting the app.
|
|
10
|
+
|
|
11
|
+
Design notes
|
|
12
|
+
------------
|
|
13
|
+
prompt_toolkit's :class:`CompletionsMenuControl.preferred_width` returns
|
|
14
|
+
``menu_width + menu_meta_width`` based on the longest completion, so the
|
|
15
|
+
menu is content-sized and the scrollbar lives wherever that content ends.
|
|
16
|
+
We replace ``preferred_width`` with a version that returns
|
|
17
|
+
``max_available_width``, causing the parent ``Window`` to stretch the menu
|
|
18
|
+
across the full row. Combined with the existing ``_left_justify_completion_menu``
|
|
19
|
+
that pins the menu's ``Float`` to column 0, the scrollbar lands flush against
|
|
20
|
+
the right edge of the screen.
|
|
21
|
+
|
|
22
|
+
The patch is:
|
|
23
|
+
|
|
24
|
+
* **Idempotent** — re-installing is a no-op (sentinel attribute).
|
|
25
|
+
* **Reversible** — original methods are stashed and restored on disable.
|
|
26
|
+
* **Defensive** — every patch step is wrapped in try/except so a
|
|
27
|
+
prompt_toolkit version bump cannot crash the prompt.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
from __future__ import annotations
|
|
31
|
+
|
|
32
|
+
from typing import List, Tuple
|
|
33
|
+
|
|
34
|
+
from code_puppy.callbacks import register_callback
|
|
35
|
+
|
|
36
|
+
_COMMAND_NAME = "widemenu"
|
|
37
|
+
_PATCH_FLAG = "_wide_completion_menu_patched"
|
|
38
|
+
_ORIGINAL_ATTR = "_wide_completion_menu_original_preferred_width"
|
|
39
|
+
|
|
40
|
+
# Module state lets /widemenu toggle without uninstalling; disabled mode delegates
|
|
41
|
+
# ``preferred_width`` to upstream.
|
|
42
|
+
_state = {"enabled": True}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
# Messaging helpers (lazy-imported to avoid boot-time cycles)
|
|
46
|
+
def _emit_info(message: str) -> None:
|
|
47
|
+
from code_puppy.messaging import emit_info
|
|
48
|
+
|
|
49
|
+
emit_info(message)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _emit_error(message: str) -> None:
|
|
53
|
+
from code_puppy.messaging import emit_error
|
|
54
|
+
|
|
55
|
+
emit_error(message)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
# Patching
|
|
59
|
+
def _patch_menu_class(cls) -> None:
|
|
60
|
+
"""Replace ``cls.preferred_width`` with a screen-filling variant.
|
|
61
|
+
|
|
62
|
+
Stores the original method on the class under ``_ORIGINAL_ATTR`` so we
|
|
63
|
+
can both delegate to it (when toggled off) and restore it cleanly.
|
|
64
|
+
"""
|
|
65
|
+
if getattr(cls, _PATCH_FLAG, False):
|
|
66
|
+
return # Already patched.
|
|
67
|
+
|
|
68
|
+
original = cls.preferred_width
|
|
69
|
+
setattr(cls, _ORIGINAL_ATTR, original)
|
|
70
|
+
|
|
71
|
+
def patched_preferred_width(self, max_available_width: int):
|
|
72
|
+
# When toggled off, behave exactly like upstream.
|
|
73
|
+
if not _state["enabled"]:
|
|
74
|
+
return original(self, max_available_width)
|
|
75
|
+
|
|
76
|
+
# Stretch only when a completion menu exists; upstream returns 0 when empty.
|
|
77
|
+
try:
|
|
78
|
+
from prompt_toolkit.application.current import get_app
|
|
79
|
+
|
|
80
|
+
complete_state = get_app().current_buffer.complete_state
|
|
81
|
+
except Exception:
|
|
82
|
+
complete_state = None
|
|
83
|
+
|
|
84
|
+
if not complete_state:
|
|
85
|
+
return 0
|
|
86
|
+
return max_available_width
|
|
87
|
+
|
|
88
|
+
cls.preferred_width = patched_preferred_width
|
|
89
|
+
setattr(cls, _PATCH_FLAG, True)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def _install_patch() -> None:
|
|
93
|
+
"""Patch both single- and multi-column completion menu controls."""
|
|
94
|
+
from prompt_toolkit.layout.menus import (
|
|
95
|
+
CompletionsMenuControl,
|
|
96
|
+
MultiColumnCompletionMenuControl,
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
_patch_menu_class(CompletionsMenuControl)
|
|
100
|
+
_patch_menu_class(MultiColumnCompletionMenuControl)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def _on_startup() -> None:
|
|
104
|
+
try:
|
|
105
|
+
_install_patch()
|
|
106
|
+
except Exception as exc:
|
|
107
|
+
# Plugin rule #4: fail gracefully — never crash the app.
|
|
108
|
+
_emit_error(f"wide_completion_menu: failed to install patch — {exc}")
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
# /widemenu slash command
|
|
112
|
+
_USAGE = "Usage: /widemenu [on|off|toggle|status]"
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def _custom_help() -> List[Tuple[str, str]]:
|
|
116
|
+
return [
|
|
117
|
+
(
|
|
118
|
+
_COMMAND_NAME,
|
|
119
|
+
"Toggle full-width completion menu (scrollbar pinned to screen edge)",
|
|
120
|
+
)
|
|
121
|
+
]
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def _handle_widemenu_command(command: str) -> bool:
|
|
125
|
+
# `command` is the full line, e.g. "/widemenu on". Strip the slash + name.
|
|
126
|
+
parts = command.strip().split()
|
|
127
|
+
arg = parts[1].lower() if len(parts) >= 2 else "status"
|
|
128
|
+
|
|
129
|
+
if arg in ("on", "enable", "true", "1"):
|
|
130
|
+
_state["enabled"] = True
|
|
131
|
+
_emit_info("🐶 widemenu: ON — scrollbar pinned to right edge of screen.")
|
|
132
|
+
elif arg in ("off", "disable", "false", "0"):
|
|
133
|
+
_state["enabled"] = False
|
|
134
|
+
_emit_info("🐶 widemenu: OFF — menu sized to content (default).")
|
|
135
|
+
elif arg in ("toggle", "t"):
|
|
136
|
+
_state["enabled"] = not _state["enabled"]
|
|
137
|
+
status = "ON" if _state["enabled"] else "OFF"
|
|
138
|
+
_emit_info(f"🐶 widemenu: {status}")
|
|
139
|
+
elif arg == "status":
|
|
140
|
+
status = "ON" if _state["enabled"] else "OFF"
|
|
141
|
+
_emit_info(f"🐶 widemenu is currently {status}. {_USAGE}")
|
|
142
|
+
else:
|
|
143
|
+
_emit_info(_USAGE)
|
|
144
|
+
return True
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def _handle_custom_command(command: str, name: str):
|
|
148
|
+
if name != _COMMAND_NAME:
|
|
149
|
+
return None
|
|
150
|
+
return _handle_widemenu_command(command)
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
# Registration
|
|
154
|
+
register_callback("startup", _on_startup)
|
|
155
|
+
register_callback("custom_command", _handle_custom_command)
|
|
156
|
+
register_callback("custom_command_help", _custom_help)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
__all__ = [
|
|
160
|
+
"_handle_custom_command",
|
|
161
|
+
"_handle_widemenu_command",
|
|
162
|
+
"_install_patch",
|
|
163
|
+
"_on_startup",
|
|
164
|
+
"_patch_menu_class",
|
|
165
|
+
]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Wiggum looping plugin."""
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"""Durable records for resumable ``/goal`` runs."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import os
|
|
7
|
+
import uuid
|
|
8
|
+
from dataclasses import asdict, dataclass
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
from code_puppy.config import STATE_DIR
|
|
12
|
+
|
|
13
|
+
_RUNS_DIR = Path(STATE_DIR) / "goal_runs"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass(frozen=True)
|
|
17
|
+
class GoalRun:
|
|
18
|
+
"""The minimum state required to continue an interrupted goal."""
|
|
19
|
+
|
|
20
|
+
run_id: str
|
|
21
|
+
prompt: str
|
|
22
|
+
loop_count: int = 0
|
|
23
|
+
remediation_notes: str | None = None
|
|
24
|
+
status: str = "active"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def create(prompt: str) -> GoalRun:
|
|
28
|
+
"""Create and persist a new goal run."""
|
|
29
|
+
run = GoalRun(run_id=str(uuid.uuid4()), prompt=prompt)
|
|
30
|
+
save(run)
|
|
31
|
+
return run
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def save(run: GoalRun) -> None:
|
|
35
|
+
"""Atomically persist a goal run."""
|
|
36
|
+
_RUNS_DIR.mkdir(parents=True, exist_ok=True)
|
|
37
|
+
destination = _path(run.run_id)
|
|
38
|
+
temporary = destination.with_suffix(f".tmp-{os.getpid()}")
|
|
39
|
+
temporary.write_text(json.dumps(asdict(run), indent=2), encoding="utf-8")
|
|
40
|
+
temporary.replace(destination)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def load(run_id: str) -> GoalRun | None:
|
|
44
|
+
"""Load a run by UUID, returning ``None`` for invalid or missing IDs."""
|
|
45
|
+
normalized = _normalize_uuid(run_id)
|
|
46
|
+
if normalized is None:
|
|
47
|
+
return None
|
|
48
|
+
try:
|
|
49
|
+
payload = json.loads(_path(normalized).read_text(encoding="utf-8"))
|
|
50
|
+
return GoalRun(
|
|
51
|
+
run_id=normalized,
|
|
52
|
+
prompt=str(payload["prompt"]),
|
|
53
|
+
loop_count=max(0, int(payload.get("loop_count", 0))),
|
|
54
|
+
remediation_notes=payload.get("remediation_notes"),
|
|
55
|
+
status=str(payload.get("status", "active")),
|
|
56
|
+
)
|
|
57
|
+
except (OSError, ValueError, TypeError, KeyError, json.JSONDecodeError):
|
|
58
|
+
return None
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def update(
|
|
62
|
+
run_id: str,
|
|
63
|
+
*,
|
|
64
|
+
loop_count: int,
|
|
65
|
+
remediation_notes: str | None,
|
|
66
|
+
status: str = "active",
|
|
67
|
+
) -> None:
|
|
68
|
+
"""Update mutable progress fields when the run still exists."""
|
|
69
|
+
run = load(run_id)
|
|
70
|
+
if run is None:
|
|
71
|
+
return
|
|
72
|
+
save(
|
|
73
|
+
GoalRun(
|
|
74
|
+
run_id=run.run_id,
|
|
75
|
+
prompt=run.prompt,
|
|
76
|
+
loop_count=loop_count,
|
|
77
|
+
remediation_notes=remediation_notes,
|
|
78
|
+
status=status,
|
|
79
|
+
)
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def _path(run_id: str) -> Path:
|
|
84
|
+
return _RUNS_DIR / f"{run_id}.json"
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def _normalize_uuid(value: str) -> str | None:
|
|
88
|
+
try:
|
|
89
|
+
return str(uuid.UUID(value.strip()))
|
|
90
|
+
except (AttributeError, ValueError):
|
|
91
|
+
return None
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
"""LLM judge helpers for goal mode.
|
|
2
|
+
|
|
3
|
+
A judge is a small, read-only pydantic_ai Agent that examines the
|
|
4
|
+
implementor's latest response (and optionally its message history) and
|
|
5
|
+
returns a structured verdict: complete/not + remediation notes.
|
|
6
|
+
|
|
7
|
+
Each judge has its own model and prompt — see ``judge_config.py`` for
|
|
8
|
+
persistence. The /goal loop fans these out in parallel; see
|
|
9
|
+
``register_callbacks._run_goal_judges``.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import asyncio
|
|
15
|
+
import json
|
|
16
|
+
from dataclasses import dataclass
|
|
17
|
+
from typing import Any
|
|
18
|
+
|
|
19
|
+
from pydantic import BaseModel, Field
|
|
20
|
+
from pydantic_ai import Agent, RunContext, ToolOutput, UsageLimits
|
|
21
|
+
|
|
22
|
+
from code_puppy.agents._history import stringify_part
|
|
23
|
+
from code_puppy.agents.agent_manager import load_agent
|
|
24
|
+
from code_puppy.model_factory import ModelFactory, make_model_settings
|
|
25
|
+
from code_puppy.model_utils import prepare_prompt_for_model
|
|
26
|
+
from code_puppy.tools.subagent_context import subagent_context
|
|
27
|
+
|
|
28
|
+
from .judge_config import DEFAULT_JUDGE_PROMPT, JudgeConfig
|
|
29
|
+
|
|
30
|
+
# Read-only judges should not need 200 requests; cap verification-heavy loops
|
|
31
|
+
# without letting a runaway judge consume the goal loop's budget.
|
|
32
|
+
GOAL_JUDGE_REQUEST_LIMIT = 200
|
|
33
|
+
|
|
34
|
+
_READ_ONLY_TOOLS = {
|
|
35
|
+
"list_files",
|
|
36
|
+
"read_file",
|
|
37
|
+
"grep",
|
|
38
|
+
"agent_run_shell_command",
|
|
39
|
+
"load_image_for_analysis",
|
|
40
|
+
"list_agents",
|
|
41
|
+
"invoke_agent",
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class GoalJudgeOutput(BaseModel):
|
|
46
|
+
"""Structured verdict from a goal judge."""
|
|
47
|
+
|
|
48
|
+
complete: bool = Field(
|
|
49
|
+
description="True only when the goal is verifiably complete."
|
|
50
|
+
)
|
|
51
|
+
notes: str = Field(
|
|
52
|
+
description="Brief rationale plus remediation notes if incomplete."
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@dataclass(frozen=True)
|
|
57
|
+
class GoalJudgement:
|
|
58
|
+
"""Final, normalized verdict surfaced to /goal callers.
|
|
59
|
+
|
|
60
|
+
``abstained`` means the judge couldn't produce a verdict for an
|
|
61
|
+
infrastructure reason — model endpoint 404, auth failure, network
|
|
62
|
+
timeout, misconfigured model, etc. Abstaining judges are excluded
|
|
63
|
+
from the all-complete tally; they neither pass nor fail the goal.
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
judge_name: str
|
|
67
|
+
complete: bool
|
|
68
|
+
notes: str
|
|
69
|
+
raw_response: str
|
|
70
|
+
abstained: bool = False
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _read_only_tools_for_implementor(agent_config: Any) -> list[str]:
|
|
74
|
+
return [
|
|
75
|
+
tool for tool in agent_config.get_available_tools() if tool in _READ_ONLY_TOOLS
|
|
76
|
+
]
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _format_message(message: Any, index: int) -> str:
|
|
80
|
+
part_lines = [stringify_part(part) for part in getattr(message, "parts", [])]
|
|
81
|
+
text = "\n".join(line for line in part_lines if line)
|
|
82
|
+
return f"[{index}] {message.__class__.__name__}:\n{text or '(empty message)'}"
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def _format_history_window(
|
|
86
|
+
messages: list[Any],
|
|
87
|
+
*,
|
|
88
|
+
query: str | None = None,
|
|
89
|
+
limit: int = 20,
|
|
90
|
+
max_chars: int = 12000,
|
|
91
|
+
) -> str:
|
|
92
|
+
if not messages:
|
|
93
|
+
return "(no implementor message history captured)"
|
|
94
|
+
|
|
95
|
+
normalized_query = (query or "").strip().lower()
|
|
96
|
+
indexed = list(enumerate(messages))
|
|
97
|
+
if normalized_query:
|
|
98
|
+
indexed = [
|
|
99
|
+
(idx, msg)
|
|
100
|
+
for idx, msg in indexed
|
|
101
|
+
if normalized_query
|
|
102
|
+
in "\n".join(
|
|
103
|
+
stringify_part(part) for part in getattr(msg, "parts", [])
|
|
104
|
+
).lower()
|
|
105
|
+
]
|
|
106
|
+
|
|
107
|
+
selected = indexed[-max(1, min(limit, 100)) :]
|
|
108
|
+
chunks: list[str] = []
|
|
109
|
+
total = 0
|
|
110
|
+
for idx, message in selected:
|
|
111
|
+
block = _format_message(message, idx)
|
|
112
|
+
if total + len(block) > max_chars:
|
|
113
|
+
remaining = max_chars - total
|
|
114
|
+
if remaining > 500:
|
|
115
|
+
chunks.append(block[:remaining])
|
|
116
|
+
break
|
|
117
|
+
chunks.append(block)
|
|
118
|
+
total += len(block)
|
|
119
|
+
|
|
120
|
+
if not chunks:
|
|
121
|
+
return "(no matching implementor history messages)"
|
|
122
|
+
return "\n\n---\n\n".join(chunks)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def _register_goal_history_tool(judge_agent: Agent, messages: list[Any]) -> None:
|
|
126
|
+
@judge_agent.tool
|
|
127
|
+
async def inspect_goal_history(
|
|
128
|
+
context: RunContext[None],
|
|
129
|
+
query: str | None = None,
|
|
130
|
+
limit: int = 20,
|
|
131
|
+
) -> str:
|
|
132
|
+
"""Inspect the /goal implementor's read-only message history.
|
|
133
|
+
|
|
134
|
+
Args:
|
|
135
|
+
query: Optional case-insensitive substring to search for in message parts.
|
|
136
|
+
limit: Maximum number of recent matching messages to return, capped at 100.
|
|
137
|
+
"""
|
|
138
|
+
del context
|
|
139
|
+
return _format_history_window(messages, query=query, limit=limit)
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def _strip_thinking_settings(model_settings: dict) -> None:
|
|
143
|
+
"""Remove thinking-related settings that conflict with ToolOutput.
|
|
144
|
+
|
|
145
|
+
Anthropic models reject thinking + tool output at the same time, and other
|
|
146
|
+
providers don't mind missing keys. We strip:
|
|
147
|
+
* `anthropic_thinking` (Anthropic / Bedrock / Azure Foundry Claude / claude_code)
|
|
148
|
+
* `thinking` (GLM-4.7 / GLM-5 style)
|
|
149
|
+
* `thinking_enabled` / `thinking_level` (Gemini)
|
|
150
|
+
* `extra_body.output_config` (effort knob that only matters with adaptive thinking)
|
|
151
|
+
"""
|
|
152
|
+
for key in ("anthropic_thinking", "thinking", "thinking_enabled", "thinking_level"):
|
|
153
|
+
model_settings.pop(key, None)
|
|
154
|
+
|
|
155
|
+
extra_body = model_settings.get("extra_body")
|
|
156
|
+
if isinstance(extra_body, dict):
|
|
157
|
+
extra_body.pop("output_config", None)
|
|
158
|
+
if not extra_body:
|
|
159
|
+
model_settings.pop("extra_body", None)
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def _judge_user_prompt(
|
|
163
|
+
goal: str,
|
|
164
|
+
response: str | None,
|
|
165
|
+
error: BaseException | None,
|
|
166
|
+
) -> str:
|
|
167
|
+
error_text = f"\nRUN ERROR:\n{error}\n" if error else ""
|
|
168
|
+
response_text = response or "(no response captured)"
|
|
169
|
+
return f"""\
|
|
170
|
+
Judge whether this coding goal is verifiably complete.
|
|
171
|
+
|
|
172
|
+
GOAL:
|
|
173
|
+
{goal}
|
|
174
|
+
|
|
175
|
+
LATEST AGENT RESPONSE:
|
|
176
|
+
{response_text}
|
|
177
|
+
{error_text}
|
|
178
|
+
You have a read-only `inspect_goal_history` tool for the /goal implementor's transcript.
|
|
179
|
+
Use it when the latest response is not enough to confidently judge completion.
|
|
180
|
+
"""
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
async def judge_goal(
|
|
184
|
+
*,
|
|
185
|
+
judge_config: JudgeConfig,
|
|
186
|
+
implementor_agent: Any,
|
|
187
|
+
goal: str,
|
|
188
|
+
response: str | None,
|
|
189
|
+
error: BaseException | None,
|
|
190
|
+
history: list[Any] | None = None,
|
|
191
|
+
) -> GoalJudgement:
|
|
192
|
+
"""Run a single fresh, read-only judge against the implementor's latest turn.
|
|
193
|
+
|
|
194
|
+
Args:
|
|
195
|
+
judge_config: The judge's persisted configuration (name, model, prompt).
|
|
196
|
+
implementor_agent: The /goal implementor's agent — used only to discover
|
|
197
|
+
which read-only tools should be available to the judge.
|
|
198
|
+
goal: The original /goal prompt.
|
|
199
|
+
response: The implementor's most recent textual response (or None).
|
|
200
|
+
error: Any exception raised on the implementor's latest turn.
|
|
201
|
+
history: The implementor's message history (read-only).
|
|
202
|
+
"""
|
|
203
|
+
from code_puppy import plugins
|
|
204
|
+
|
|
205
|
+
plugins.load_plugin_callbacks()
|
|
206
|
+
|
|
207
|
+
model_name = judge_config.model
|
|
208
|
+
models_config = ModelFactory.load_config()
|
|
209
|
+
if model_name not in models_config:
|
|
210
|
+
# Misconfigured model is an infrastructure issue, not a real
|
|
211
|
+
# judgement — abstain so we don't block /goal on it.
|
|
212
|
+
return GoalJudgement(
|
|
213
|
+
judge_name=judge_config.name,
|
|
214
|
+
complete=False,
|
|
215
|
+
notes=(f"model {model_name!r} not present in the model config"),
|
|
216
|
+
raw_response="",
|
|
217
|
+
abstained=True,
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
model = ModelFactory.get_model(model_name, models_config)
|
|
221
|
+
judge_instructions = judge_config.prompt or DEFAULT_JUDGE_PROMPT
|
|
222
|
+
user_prompt = _judge_user_prompt(goal, response, error)
|
|
223
|
+
prepared = prepare_prompt_for_model(
|
|
224
|
+
model_name,
|
|
225
|
+
judge_instructions,
|
|
226
|
+
user_prompt,
|
|
227
|
+
prepend_system_to_user=True,
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
model_settings = make_model_settings(model_name)
|
|
231
|
+
_strip_thinking_settings(model_settings)
|
|
232
|
+
|
|
233
|
+
judge_agent = Agent(
|
|
234
|
+
model=model,
|
|
235
|
+
instructions=prepared.instructions,
|
|
236
|
+
output_type=ToolOutput(
|
|
237
|
+
GoalJudgeOutput,
|
|
238
|
+
name="goal_judgement",
|
|
239
|
+
description="Verdict for the /goal implementor's latest iteration.",
|
|
240
|
+
),
|
|
241
|
+
retries=3,
|
|
242
|
+
model_settings=model_settings,
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
# Give the judge the same read-only tools the implementor has, so it can
|
|
246
|
+
# poke at files/run tests/etc to verify completion.
|
|
247
|
+
from code_puppy.tools import register_tools_for_agent
|
|
248
|
+
|
|
249
|
+
try:
|
|
250
|
+
implementor_config = load_agent(implementor_agent.name)
|
|
251
|
+
read_only_tools = _read_only_tools_for_implementor(implementor_config)
|
|
252
|
+
except Exception:
|
|
253
|
+
read_only_tools = []
|
|
254
|
+
|
|
255
|
+
register_tools_for_agent(
|
|
256
|
+
judge_agent,
|
|
257
|
+
read_only_tools,
|
|
258
|
+
model_name=model_name,
|
|
259
|
+
)
|
|
260
|
+
_register_goal_history_tool(judge_agent, list(history or []))
|
|
261
|
+
|
|
262
|
+
# Run judges as sub-agents to suppress tool/reasoning chatter; rich_renderer
|
|
263
|
+
# and tools/display already skip those banners in sub-agent context.
|
|
264
|
+
try:
|
|
265
|
+
with subagent_context(f"judge:{judge_config.name}"):
|
|
266
|
+
result = await judge_agent.run(
|
|
267
|
+
prepared.user_prompt,
|
|
268
|
+
usage_limits=UsageLimits(request_limit=GOAL_JUDGE_REQUEST_LIMIT),
|
|
269
|
+
)
|
|
270
|
+
output = result.output
|
|
271
|
+
except (asyncio.CancelledError, KeyboardInterrupt):
|
|
272
|
+
# Propagate cancellation — the orchestrator handles cleanup.
|
|
273
|
+
raise
|
|
274
|
+
except Exception as exc:
|
|
275
|
+
# Infrastructure errors abstain rather than vote; the judge produced no
|
|
276
|
+
# verdict to fail the goal.
|
|
277
|
+
return GoalJudgement(
|
|
278
|
+
judge_name=judge_config.name,
|
|
279
|
+
complete=False,
|
|
280
|
+
notes=f"endpoint error ({type(exc).__name__}): {exc}",
|
|
281
|
+
raw_response="",
|
|
282
|
+
abstained=True,
|
|
283
|
+
)
|
|
284
|
+
|
|
285
|
+
if hasattr(output, "model_dump_json"):
|
|
286
|
+
raw = output.model_dump_json()
|
|
287
|
+
complete = output.complete
|
|
288
|
+
notes = output.notes
|
|
289
|
+
else:
|
|
290
|
+
raw = json.dumps(output)
|
|
291
|
+
complete = bool(output.get("complete"))
|
|
292
|
+
notes = str(output.get("notes", ""))
|
|
293
|
+
|
|
294
|
+
return GoalJudgement(
|
|
295
|
+
judge_name=judge_config.name,
|
|
296
|
+
complete=complete,
|
|
297
|
+
notes=notes,
|
|
298
|
+
raw_response=raw,
|
|
299
|
+
)
|