code-puppy 0.0.593__tar.gz → 0.0.595__tar.gz
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-0.0.593 → code_puppy-0.0.595}/PKG-INFO +1 -1
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/agents/_key_listeners.py +57 -5
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/agents/_runtime.py +104 -104
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/callbacks.py +0 -19
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/claude_cache_client.py +2 -9
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/messaging/run_ui.py +44 -5
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/claude_code_oauth/README.md +0 -4
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/claude_code_oauth/register_callbacks.py +0 -5
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/claude_code_oauth/utils.py +0 -22
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/tools/ask_user_question/terminal_ui.py +12 -13
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/tools/command_runner.py +38 -14
- {code_puppy-0.0.593 → code_puppy-0.0.595}/pyproject.toml +1 -1
- code_puppy-0.0.593/code_puppy/plugins/claude_code_oauth/auth_retry.py +0 -213
- {code_puppy-0.0.593 → code_puppy-0.0.595}/.gitignore +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/LICENSE +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/README.md +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/__main__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/agents/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/agents/_builder.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/agents/_compaction.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/agents/_diagnostics.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/agents/_history.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/agents/_non_streaming_render.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/agents/_run_signals.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/agents/_steer_processor.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/agents/agent_code_puppy.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/agents/agent_creator_agent.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/agents/agent_helios.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/agents/agent_manager.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/agents/agent_planning.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/agents/agent_qa_kitten.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/agents/base_agent.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/agents/event_stream_handler.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/agents/json_agent.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/agents/run_stats.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/agents/smooth_stream.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/agents/subagent_stream_handler.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/chatgpt_codex_client.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/cli_runner.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/add_model_menu.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/agent_menu.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/attachments.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/autosave_menu.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/autosave_search.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/clipboard.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/colors_menu.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/command_handler.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/command_registry.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/config_apply.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/config_commands.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/core_commands.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/diff_menu.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/file_index.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/file_path_completion.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/judges_menu.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/load_context_completion.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/mcp/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/mcp/base.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/mcp/catalog_server_installer.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/mcp/custom_server_form.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/mcp/custom_server_installer.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/mcp/edit_command.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/mcp/handler.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/mcp/help_command.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/mcp/install_command.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/mcp/install_menu.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/mcp/list_command.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/mcp/logs_command.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/mcp/remove_command.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/mcp/restart_command.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/mcp/search_command.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/mcp/silence_warning_command.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/mcp/start_all_command.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/mcp/start_command.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/mcp/status_command.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/mcp/stop_all_command.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/mcp/stop_command.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/mcp/utils.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/mcp/wizard_utils.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/mcp_binding_menu.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/mcp_completion.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/model_picker_completion.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/model_settings_menu.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/onboarding_slides.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/onboarding_wizard.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/pagination.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/pin_command_completion.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/prompt_toolkit_completion.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/session_commands.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/set_menu.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/set_menu_catalog.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/set_menu_render.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/set_menu_schema.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/set_menu_settings.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/set_menu_shims.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/set_menu_values.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/shell_passthrough.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/skills_completion.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/uc_menu.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/utils.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/command_line/wiggum_state.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/config.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/error_logging.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/gemini_code_assist.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/gemini_model.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/hook_engine/README.md +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/hook_engine/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/hook_engine/aliases.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/hook_engine/engine.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/hook_engine/executor.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/hook_engine/matcher.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/hook_engine/models.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/hook_engine/registry.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/hook_engine/validator.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/http_utils.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/keymap.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/list_filtering.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/main.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/mcp_/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/mcp_/agent_bindings.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/mcp_/async_lifecycle.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/mcp_/blocking_startup.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/mcp_/captured_stdio_server.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/mcp_/circuit_breaker.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/mcp_/config_wizard.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/mcp_/dashboard.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/mcp_/error_isolation.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/mcp_/examples/retry_example.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/mcp_/health_monitor.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/mcp_/managed_server.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/mcp_/manager.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/mcp_/mcp_logs.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/mcp_/registry.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/mcp_/retry_manager.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/mcp_/server_registry_catalog.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/mcp_/status_tracker.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/mcp_/system_tools.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/mcp_/tool_arg_coercion.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/mcp_prompts/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/mcp_prompts/hook_creator.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/messaging/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/messaging/bar_painters.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/messaging/bar_rendering.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/messaging/bottom_bar.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/messaging/bus.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/messaging/commands.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/messaging/editor_actions.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/messaging/editor_completion.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/messaging/editor_display.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/messaging/editor_history.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/messaging/editor_keys.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/messaging/editor_paste.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/messaging/line_editor.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/messaging/markdown_patches.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/messaging/message_queue.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/messaging/messages.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/messaging/pause_controller.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/messaging/prompt_prefix_style.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/messaging/queue_console.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/messaging/renderers.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/messaging/rich_renderer.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/messaging/run_ui_wiring.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/messaging/spinner/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/messaging/subagent_console.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/model_descriptions.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/model_factory.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/model_switching.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/model_utils.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/models.json +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/models_dev_api.json +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/models_dev_parser.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/agent_skills/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/agent_skills/config.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/agent_skills/discovery.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/agent_skills/downloader.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/agent_skills/enabled_skills.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/agent_skills/installer.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/agent_skills/metadata.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/agent_skills/prompt_builder.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/agent_skills/register_callbacks.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/agent_skills/remote_catalog.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/agent_skills/skill_catalog.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/agent_skills/skill_commands.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/agent_skills/skills_install_menu.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/agent_skills/skills_menu.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/aws_bedrock/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/aws_bedrock/config.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/aws_bedrock/register_callbacks.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/aws_bedrock/utils.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/azure_foundry/README.md +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/azure_foundry/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/azure_foundry/config.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/azure_foundry/discovery.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/azure_foundry/register_callbacks.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/azure_foundry/token.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/azure_foundry/utils.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/btw/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/btw/inline_view.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/btw/register_callbacks.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/btw/side_query.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/chatgpt_oauth/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/chatgpt_oauth/config.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/chatgpt_oauth/oauth_flow.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/chatgpt_oauth/register_callbacks.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/chatgpt_oauth/test_plugin.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/chatgpt_oauth/utils.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/claude_code_hooks/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/claude_code_hooks/config.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/claude_code_hooks/register_callbacks.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/claude_code_oauth/SETUP.md +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/claude_code_oauth/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/claude_code_oauth/config.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/claude_code_oauth/fast_mode.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/claude_code_oauth/prompt_handler.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/claude_code_oauth/test_fast_mode.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/claude_code_oauth/test_plugin.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/claude_code_oauth/token_refresh_heartbeat.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/code_puppy_agent/SKILL.md +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/code_puppy_agent/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/code_puppy_agent/register_callbacks.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/config.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/context_indicator/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/context_indicator/register_callbacks.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/context_indicator/usage.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/copilot_auth/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/copilot_auth/config.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/copilot_auth/reasoning_client.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/copilot_auth/register_callbacks.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/copilot_auth/utils.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/customizable_commands/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/customizable_commands/register_callbacks.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/dbos_durable_exec/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/dbos_durable_exec/cancel.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/dbos_durable_exec/commands.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/dbos_durable_exec/config.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/dbos_durable_exec/lifecycle.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/dbos_durable_exec/register_callbacks.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/dbos_durable_exec/runtime.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/dbos_durable_exec/startup_lock.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/dbos_durable_exec/workflow_ids.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/dbos_durable_exec/wrapper.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/destructive_command_guard/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/destructive_command_guard/detector.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/destructive_command_guard/register_callbacks.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/emoji_filter/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/emoji_filter/config.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/emoji_filter/register_callbacks.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/emoji_filter/stripper.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/example_custom_command/README.md +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/example_custom_command/register_callbacks.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/file_permission_handler/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/file_permission_handler/register_callbacks.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/force_push_guard/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/force_push_guard/detector.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/force_push_guard/register_callbacks.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/force_push_guard/test_detector.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/frontend_emitter/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/frontend_emitter/emitter.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/frontend_emitter/register_callbacks.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/frontend_emitter/session_context.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/hook_creator/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/hook_creator/register_callbacks.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/hook_manager/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/hook_manager/config.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/hook_manager/hooks_menu.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/hook_manager/register_callbacks.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/oauth_puppy_html.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/obsidian_agent/README.md +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/obsidian_agent/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/obsidian_agent/agent_obsidian.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/obsidian_agent/register_callbacks.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/ollama/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/ollama/register_callbacks.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/ollama_setup/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/ollama_setup/completer.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/ollama_setup/register_callbacks.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/plugin_list/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/plugin_list/plugin_contributions.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/plugin_list/plugin_meta.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/plugin_list/plugin_text_utils.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/plugin_list/plugins_menu.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/plugin_list/plugins_menu_render.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/plugin_list/register_callbacks.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/pop_command/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/pop_command/register_callbacks.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/prompt_newline/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/prompt_newline/config.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/prompt_newline/register_callbacks.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/prune/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/prune/prune_menu.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/prune/prune_model.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/prune/prune_render.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/prune/register_callbacks.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/puppy_kennel/README.md +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/puppy_kennel/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/puppy_kennel/commands.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/puppy_kennel/config.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/puppy_kennel/kennel.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/puppy_kennel/packer.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/puppy_kennel/recorder.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/puppy_kennel/register_callbacks.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/puppy_kennel/retriever.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/puppy_kennel/schema.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/puppy_kennel/state.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/puppy_kennel/tools.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/puppy_kennel/wings.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/puppy_spinner/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/puppy_spinner/register_callbacks.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/quick_resume/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/quick_resume/register_callbacks.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/review_pr/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/review_pr/register_callbacks.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/shell_safety/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/shell_safety/agent_shell_safety.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/shell_safety/command_cache.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/shell_safety/register_callbacks.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/statusline/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/statusline/config.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/statusline/payload.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/statusline/prompt_patch.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/statusline/register_callbacks.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/statusline/runner.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/statusline/statusline_command.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/steer_queue/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/steer_queue/queue_menu.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/steer_queue/register_callbacks.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/subagent_panel/README.md +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/subagent_panel/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/subagent_panel/coalesce_patch.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/subagent_panel/panel_render.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/subagent_panel/register_callbacks.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/subagent_panel/resume_repaint.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/subagent_panel/state.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/switch_agent_resume/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/switch_agent_resume/register_callbacks.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/theme/README.md +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/theme/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/theme/bundled_palettes.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/theme/content_styles.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/theme/osc_palette.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/theme/picker.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/theme/register_callbacks.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/theme/rich_themes.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/theme/themes.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/token_ratio_learner/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/token_ratio_learner/ratios.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/token_ratio_learner/register_callbacks.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/universal_constructor/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/universal_constructor/models.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/universal_constructor/register_callbacks.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/universal_constructor/registry.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/universal_constructor/sandbox.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/wide_completion_menu/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/wide_completion_menu/register_callbacks.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/wiggum/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/wiggum/judge.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/wiggum/judge_config.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/wiggum/register_callbacks.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/wiggum/state.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/provider_credentials.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/provider_identity.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/pydantic_patches.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/reopenable_async_client.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/round_robin_model.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/session_lifecycle.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/session_migration.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/session_storage.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/status_display.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/summarization_agent.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/terminal_utils.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/tools/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/tools/agent_tools.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/tools/ask_user_question/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/tools/ask_user_question/constants.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/tools/ask_user_question/demo_tui.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/tools/ask_user_question/handler.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/tools/ask_user_question/models.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/tools/ask_user_question/registration.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/tools/ask_user_question/renderers.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/tools/ask_user_question/theme.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/tools/ask_user_question/tui_loop.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/tools/browser/__init__.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/tools/browser/browser_control.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/tools/browser/browser_interactions.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/tools/browser/browser_locators.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/tools/browser/browser_manager.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/tools/browser/browser_navigation.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/tools/browser/browser_screenshot.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/tools/browser/browser_scripts.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/tools/browser/browser_workflows.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/tools/common.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/tools/display.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/tools/file_modifications.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/tools/file_operations.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/tools/image_tools.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/tools/model_tools.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/tools/skills_tools.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/tools/subagent_context.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/tools/subagent_invocation.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/tools/tools_content.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/tools/universal_constructor.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/undo_manager.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/uvx_detection.py +0 -0
- {code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/version_checker.py +0 -0
|
@@ -200,6 +200,38 @@ def get_active_handle() -> Optional[KeyListenerHandle]:
|
|
|
200
200
|
return _active_handle
|
|
201
201
|
|
|
202
202
|
|
|
203
|
+
def acquire_listener(
|
|
204
|
+
stop_event: threading.Event,
|
|
205
|
+
on_escape: Callable[[], None],
|
|
206
|
+
on_cancel_agent: Optional[Callable[[], None]] = None,
|
|
207
|
+
) -> tuple[Optional[KeyListenerHandle], bool]:
|
|
208
|
+
"""Atomically reuse the live active listener or spawn + register one.
|
|
209
|
+
|
|
210
|
+
The historical bug: three call sites each did ``get_active_handle()``
|
|
211
|
+
→ ``spawn_key_listener()`` → ``set_active_handle()`` as separate steps,
|
|
212
|
+
so two components racing through that window could both spawn — two
|
|
213
|
+
cbreak readers on one stdin, keystrokes split between them.
|
|
214
|
+
|
|
215
|
+
Returns:
|
|
216
|
+
``(handle, spawned)`` — ``spawned`` is False when an existing live
|
|
217
|
+
listener was reused (the caller must NOT stop it). ``handle`` is
|
|
218
|
+
``None`` (with ``spawned=True``) when stdin isn't a TTY.
|
|
219
|
+
"""
|
|
220
|
+
global _active_handle
|
|
221
|
+
with _active_handle_lock:
|
|
222
|
+
existing = _active_handle
|
|
223
|
+
if (
|
|
224
|
+
existing is not None
|
|
225
|
+
and existing.thread.is_alive()
|
|
226
|
+
and not existing.stop_event.is_set()
|
|
227
|
+
):
|
|
228
|
+
return existing, False
|
|
229
|
+
handle = spawn_key_listener(stop_event, on_escape, on_cancel_agent)
|
|
230
|
+
if handle is not None:
|
|
231
|
+
_active_handle = handle
|
|
232
|
+
return handle, True
|
|
233
|
+
|
|
234
|
+
|
|
203
235
|
# =============================================================================
|
|
204
236
|
# Spawn
|
|
205
237
|
# =============================================================================
|
|
@@ -329,14 +361,24 @@ def _wait_while_suspended(
|
|
|
329
361
|
Sets ``released_event`` (when given) to confirm we've parked. Polls
|
|
330
362
|
every 50ms so we still respond to stop in a reasonable time.
|
|
331
363
|
|
|
364
|
+
The ack is LEVEL-triggered — re-asserted every lap — not edge-
|
|
365
|
+
triggered at park entry only. Rationale: back-to-back suspensions
|
|
366
|
+
(e.g. ``/resume``: one scope around ``handle_command``, another
|
|
367
|
+
around the picker) can resume+re-suspend within one 50ms poll lap.
|
|
368
|
+
The re-suspend clears ``released_event`` while we're STILL parked in
|
|
369
|
+
this loop (``suspend_event`` never read as clear), so an entry-only
|
|
370
|
+
ack would never be re-set and the new suspend would falsely time
|
|
371
|
+
out ("Key listener did not release stdin in time") even though
|
|
372
|
+
stdin was released the whole time.
|
|
373
|
+
|
|
332
374
|
NOTE: we deliberately wait on ``stop_event`` (which is unset) rather
|
|
333
375
|
than ``suspend_event`` (which IS set while we're parked here — waiting
|
|
334
376
|
on it returns immediately and busy-spins, hogging the GIL and making
|
|
335
377
|
raw-mode input prompts feel laggy while the listener is suspended).
|
|
336
378
|
"""
|
|
337
|
-
if released_event is not None:
|
|
338
|
-
released_event.set()
|
|
339
379
|
while suspend_event.is_set() and not stop_event.is_set():
|
|
380
|
+
if released_event is not None:
|
|
381
|
+
released_event.set()
|
|
340
382
|
stop_event.wait(timeout=0.05)
|
|
341
383
|
|
|
342
384
|
|
|
@@ -656,9 +698,18 @@ def suspended_key_listener(timeout: float = 1.0) -> Iterator[None]:
|
|
|
656
698
|
if _suspend_depth == 1 and handle is not None:
|
|
657
699
|
is_outermost = True
|
|
658
700
|
if is_outermost:
|
|
659
|
-
#
|
|
660
|
-
#
|
|
661
|
-
|
|
701
|
+
# A silently-failed suspend means the caller launches its own stdin
|
|
702
|
+
# reader (prompt_toolkit, input()) while the listener is STILL in
|
|
703
|
+
# cbreak mode — two readers, keystrokes split between them. Give
|
|
704
|
+
# the listener one extended grace period, then warn loudly so the
|
|
705
|
+
# flakiness is at least diagnosable instead of "sometimes my keys
|
|
706
|
+
# vanish".
|
|
707
|
+
if not handle.suspend(timeout=timeout):
|
|
708
|
+
if not handle.released_event.wait(timeout=2.0):
|
|
709
|
+
emit_warning(
|
|
710
|
+
"Key listener did not release stdin in time; "
|
|
711
|
+
"input may be flaky until this prompt closes."
|
|
712
|
+
)
|
|
662
713
|
try:
|
|
663
714
|
yield
|
|
664
715
|
finally:
|
|
@@ -671,6 +722,7 @@ def suspended_key_listener(timeout: float = 1.0) -> Iterator[None]:
|
|
|
671
722
|
|
|
672
723
|
__all__ = [
|
|
673
724
|
"KeyListenerHandle",
|
|
725
|
+
"acquire_listener",
|
|
674
726
|
"get_active_handle",
|
|
675
727
|
"get_line_editor",
|
|
676
728
|
"set_active_handle",
|
|
@@ -19,7 +19,6 @@ from __future__ import annotations
|
|
|
19
19
|
import asyncio
|
|
20
20
|
import signal
|
|
21
21
|
import threading
|
|
22
|
-
import time
|
|
23
22
|
import uuid
|
|
24
23
|
from contextlib import AsyncExitStack
|
|
25
24
|
from typing import Any, Callable, Iterator, List, Optional, Sequence, Type, Union
|
|
@@ -82,7 +81,6 @@ from code_puppy.agents._run_signals import (
|
|
|
82
81
|
from code_puppy.agents.event_stream_handler import event_stream_handler
|
|
83
82
|
from code_puppy.callbacks import (
|
|
84
83
|
on_agent_exception,
|
|
85
|
-
on_agent_retryable_exception,
|
|
86
84
|
on_agent_run_cancel,
|
|
87
85
|
on_agent_run_context,
|
|
88
86
|
on_agent_run_end,
|
|
@@ -268,37 +266,9 @@ def should_retry_streaming(exc: Exception) -> bool:
|
|
|
268
266
|
return any(_is_retryable_one(e) for e in _walk_cause_chain(exc))
|
|
269
267
|
|
|
270
268
|
|
|
271
|
-
async def _plugin_says_retry(
|
|
272
|
-
exc: Exception,
|
|
273
|
-
model_name: Optional[str],
|
|
274
|
-
attempt: int,
|
|
275
|
-
max_attempts: int,
|
|
276
|
-
) -> bool:
|
|
277
|
-
"""Ask ``agent_retryable_exception`` hooks whether ``exc`` is retryable.
|
|
278
|
-
|
|
279
|
-
Gives plugins a chance to (a) classify provider-specific failures the
|
|
280
|
-
core classifier can't know about and (b) perform recovery work (e.g. an
|
|
281
|
-
OAuth token refresh) before the retry fires. Any truthy result means
|
|
282
|
-
retry. Hook machinery failures are swallowed: a broken plugin must never
|
|
283
|
-
turn a genuine error into a hang, nor a retryable blip into a crash.
|
|
284
|
-
"""
|
|
285
|
-
try:
|
|
286
|
-
results = await on_agent_retryable_exception(
|
|
287
|
-
exc,
|
|
288
|
-
model_name=model_name,
|
|
289
|
-
attempt=attempt,
|
|
290
|
-
max_attempts=max_attempts,
|
|
291
|
-
)
|
|
292
|
-
except Exception: # pragma: no cover - defensive
|
|
293
|
-
return False
|
|
294
|
-
return any(bool(r) for r in results)
|
|
295
|
-
|
|
296
|
-
|
|
297
269
|
def streaming_retry(
|
|
298
270
|
max_attempts: int = 3,
|
|
299
271
|
delays: Sequence[float] = (1, 2, 4),
|
|
300
|
-
model_name: Optional[str] = None,
|
|
301
|
-
progress_window: float = 120.0,
|
|
302
272
|
) -> Callable[[Callable[[], Any]], Callable[[], Any]]:
|
|
303
273
|
"""Wrap a no-arg async callable with streaming-retry semantics.
|
|
304
274
|
|
|
@@ -308,48 +278,34 @@ def streaming_retry(
|
|
|
308
278
|
get the exception type, message, traceback, and which attempt it was. The
|
|
309
279
|
on-disk log is the only way to measure the upstream-blip rate after the
|
|
310
280
|
classifier silently absorbs it.
|
|
311
|
-
|
|
312
|
-
Exceptions the built-in classifier rejects get one more chance via the
|
|
313
|
-
``agent_retryable_exception`` hook, so plugins can opt provider-specific
|
|
314
|
-
failures (e.g. OAuth auth errors) into this same retry schedule.
|
|
315
|
-
``model_name`` is forwarded to the hook so plugins can scope themselves.
|
|
316
|
-
|
|
317
|
-
``max_attempts`` caps *consecutive rapid* failures, not total failures
|
|
318
|
-
per run. An agent run wraps many model calls; a long run can hit several
|
|
319
|
-
unrelated provider blips spread across minutes of successful work. If an
|
|
320
|
-
attempt survives at least ``progress_window`` seconds before failing, it
|
|
321
|
-
clearly made progress, so the failure streak resets and the blip gets a
|
|
322
|
-
fresh retry budget. Only back-to-back quick failures — the actual
|
|
323
|
-
hopeless-loop signature — burn through the cap.
|
|
324
281
|
"""
|
|
325
282
|
from code_puppy.error_logging import log_error
|
|
326
283
|
|
|
327
284
|
def decorator(factory: Callable[[], Any]) -> Callable[[], Any]:
|
|
328
285
|
async def runner() -> Any:
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
attempt_started = time.monotonic()
|
|
286
|
+
last_exc: Optional[Exception] = None
|
|
287
|
+
for attempt in range(max_attempts):
|
|
332
288
|
try:
|
|
333
289
|
return await factory()
|
|
334
290
|
except Exception as exc:
|
|
335
|
-
|
|
336
|
-
time.monotonic() - attempt_started >= progress_window
|
|
337
|
-
)
|
|
338
|
-
if not should_retry_streaming(exc) and not await _plugin_says_retry(
|
|
339
|
-
exc, model_name, streak + 1, max_attempts
|
|
340
|
-
):
|
|
291
|
+
if not should_retry_streaming(exc):
|
|
341
292
|
raise
|
|
342
|
-
|
|
343
|
-
streak = 0
|
|
344
|
-
streak += 1
|
|
293
|
+
last_exc = exc
|
|
345
294
|
log_error(
|
|
346
295
|
exc,
|
|
347
296
|
context=(
|
|
348
297
|
f"streaming_retry: transient exception on attempt "
|
|
349
|
-
f"{
|
|
298
|
+
f"{attempt + 1}/{max_attempts}"
|
|
350
299
|
),
|
|
351
300
|
)
|
|
352
|
-
if
|
|
301
|
+
if attempt < max_attempts - 1:
|
|
302
|
+
delay = delays[attempt] if attempt < len(delays) else delays[-1]
|
|
303
|
+
emit_warning(
|
|
304
|
+
f"\u26a1 Streaming interrupted, auto-retrying in {delay}s... "
|
|
305
|
+
f"(attempt {attempt + 1}/{max_attempts})"
|
|
306
|
+
)
|
|
307
|
+
await asyncio.sleep(delay)
|
|
308
|
+
else:
|
|
353
309
|
log_error(
|
|
354
310
|
exc,
|
|
355
311
|
context=(
|
|
@@ -360,15 +316,8 @@ def streaming_retry(
|
|
|
360
316
|
emit_error(
|
|
361
317
|
f"\u274c Streaming failed after {max_attempts} attempts"
|
|
362
318
|
)
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
delays[streak - 1] if streak - 1 < len(delays) else delays[-1]
|
|
366
|
-
)
|
|
367
|
-
emit_warning(
|
|
368
|
-
f"\u26a1 Streaming interrupted, auto-retrying in {delay}s... "
|
|
369
|
-
f"(attempt {streak}/{max_attempts})"
|
|
370
|
-
)
|
|
371
|
-
await asyncio.sleep(delay)
|
|
319
|
+
assert last_exc is not None # loop always sets this before exiting
|
|
320
|
+
raise last_exc
|
|
372
321
|
|
|
373
322
|
return runner
|
|
374
323
|
|
|
@@ -482,6 +431,16 @@ def _collect_exceptions(
|
|
|
482
431
|
# ---- The main entry point ---------------------------------------------------
|
|
483
432
|
|
|
484
433
|
|
|
434
|
+
# Depth of in-flight ``run_with_mcp`` calls. Only touched from the main
|
|
435
|
+
# event loop's thread (every run is awaited on the same loop), so a plain
|
|
436
|
+
# int is race-free. Depth > 0 at entry means a NESTED run — e.g. the
|
|
437
|
+
# shell_safety plugin assessing a command while the primary agent runs.
|
|
438
|
+
# Nested runs must NOT touch process-wide interactive state: the
|
|
439
|
+
# PauseController (it would drain the user's queued steers!), the SIGINT
|
|
440
|
+
# handler, the shell cancel bridge, or the key-listener cancel hotkey.
|
|
441
|
+
_active_run_depth = 0
|
|
442
|
+
|
|
443
|
+
|
|
485
444
|
async def run_with_mcp(
|
|
486
445
|
agent: Any,
|
|
487
446
|
prompt: str,
|
|
@@ -491,13 +450,48 @@ async def run_with_mcp(
|
|
|
491
450
|
output_type: Optional[Type[Any]] = None,
|
|
492
451
|
**kwargs: Any,
|
|
493
452
|
) -> Any:
|
|
494
|
-
"""Run ``agent`` against ``prompt`` with full MCP + cancellation support.
|
|
453
|
+
"""Run ``agent`` against ``prompt`` with full MCP + cancellation support.
|
|
454
|
+
|
|
455
|
+
Thin depth-tracking wrapper: nested calls (a run started while another
|
|
456
|
+
run is already in flight on this loop) skip the interactive-state
|
|
457
|
+
plumbing — see ``_active_run_depth``.
|
|
458
|
+
"""
|
|
459
|
+
global _active_run_depth
|
|
460
|
+
is_nested_run = _active_run_depth > 0
|
|
461
|
+
_active_run_depth += 1
|
|
462
|
+
try:
|
|
463
|
+
return await _run_with_mcp_impl(
|
|
464
|
+
agent,
|
|
465
|
+
prompt,
|
|
466
|
+
attachments=attachments,
|
|
467
|
+
link_attachments=link_attachments,
|
|
468
|
+
output_type=output_type,
|
|
469
|
+
is_nested_run=is_nested_run,
|
|
470
|
+
**kwargs,
|
|
471
|
+
)
|
|
472
|
+
finally:
|
|
473
|
+
_active_run_depth -= 1
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
async def _run_with_mcp_impl(
|
|
477
|
+
agent: Any,
|
|
478
|
+
prompt: str,
|
|
479
|
+
*,
|
|
480
|
+
attachments: Optional[Sequence[BinaryContent]] = None,
|
|
481
|
+
link_attachments: Optional[Sequence[Union[ImageUrl, DocumentUrl]]] = None,
|
|
482
|
+
output_type: Optional[Type[Any]] = None,
|
|
483
|
+
is_nested_run: bool = False,
|
|
484
|
+
**kwargs: Any,
|
|
485
|
+
) -> Any:
|
|
486
|
+
"""Body of :func:`run_with_mcp` (depth bookkeeping lives in the wrapper)."""
|
|
495
487
|
|
|
496
488
|
# Scrub any stale PauseController state from a previously-cancelled run
|
|
497
489
|
# BEFORE we touch the prompt or build the agent. The controller is a
|
|
498
490
|
# process-wide singleton; without this guard a leftover steer queue
|
|
499
|
-
# would silently poison this run.
|
|
500
|
-
|
|
491
|
+
# would silently poison this run. NEVER from a nested run: the "stale"
|
|
492
|
+
# steers it would drain are the OUTER run's live ones.
|
|
493
|
+
if not is_nested_run:
|
|
494
|
+
reset_pause_state_at_run_start()
|
|
501
495
|
|
|
502
496
|
prompt = _sanitize_prompt(prompt)
|
|
503
497
|
group_id = str(uuid.uuid4())
|
|
@@ -542,7 +536,7 @@ async def run_with_mcp(
|
|
|
542
536
|
# the non-streaming fallback render.
|
|
543
537
|
skip_fallback_render = on_should_skip_fallback_render(agent)
|
|
544
538
|
|
|
545
|
-
@streaming_retry(
|
|
539
|
+
@streaming_retry()
|
|
546
540
|
async def _call() -> Any:
|
|
547
541
|
return await pydantic_agent.run(
|
|
548
542
|
prompt_to_use,
|
|
@@ -582,7 +576,7 @@ async def run_with_mcp(
|
|
|
582
576
|
# between ``agent.run()`` calls below — additive, won't interrupt
|
|
583
577
|
# in-progress work.
|
|
584
578
|
async def _follow_up_run(follow_up_prompt: Any) -> Any:
|
|
585
|
-
@streaming_retry(
|
|
579
|
+
@streaming_retry()
|
|
586
580
|
async def _call_follow_up() -> Any:
|
|
587
581
|
return await pydantic_agent.run(
|
|
588
582
|
follow_up_prompt,
|
|
@@ -766,10 +760,12 @@ async def run_with_mcp(
|
|
|
766
760
|
# Bridge the cancel callback to the shell SIGINT handler so a single
|
|
767
761
|
# Ctrl+C while shells are running stops the whole agent/sub-agent swarm
|
|
768
762
|
# (kill shells, then cancel every task) instead of only killing the
|
|
769
|
-
# current batch of shells.
|
|
763
|
+
# current batch of shells. Nested runs must not clobber the outer
|
|
764
|
+
# run's bridge (clear_agent_cancel in their finally would disarm it).
|
|
770
765
|
from code_puppy.tools import command_runner as _command_runner
|
|
771
766
|
|
|
772
|
-
|
|
767
|
+
if not is_nested_run:
|
|
768
|
+
_command_runner.register_agent_cancel(schedule_agent_cancel)
|
|
773
769
|
|
|
774
770
|
def keyboard_interrupt_handler(_sig, _frame):
|
|
775
771
|
# Let input() handle its own KeyboardInterrupt if we're mid-prompt.
|
|
@@ -820,27 +816,25 @@ async def run_with_mcp(
|
|
|
820
816
|
run_usage_output_tokens: Optional[int] = None
|
|
821
817
|
|
|
822
818
|
try:
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
_key_listeners.set_cancel_handler(cancel_cb)
|
|
841
|
-
else:
|
|
819
|
+
# Nested runs (e.g. shell_safety mid-run) leave the SIGINT handler
|
|
820
|
+
# and cancel hotkey alone — the outer run owns them, and cancelling
|
|
821
|
+
# the outer task propagates into this awaited one anyway.
|
|
822
|
+
if not is_nested_run:
|
|
823
|
+
if cancel_agent_uses_signal():
|
|
824
|
+
original_handler = signal.signal(
|
|
825
|
+
signal.SIGINT, keyboard_interrupt_handler
|
|
826
|
+
)
|
|
827
|
+
cancel_cb: Optional[Callable[[], None]] = None # SIGINT owns cancel
|
|
828
|
+
else:
|
|
829
|
+
original_handler = signal.signal(signal.SIGINT, graceful_sigint_handler)
|
|
830
|
+
cancel_cb = schedule_agent_cancel
|
|
831
|
+
# Key listener: with the persistent prompt (Phase A) a REPL-
|
|
832
|
+
# lifetime listener already owns stdin — just arm the per-run
|
|
833
|
+
# cancel hotkey on it. Otherwise (headless -r, classic prompt,
|
|
834
|
+
# embeds) spawn a per-run listener. ``acquire_listener`` makes
|
|
835
|
+
# the reuse-or-spawn decision atomic (no double-reader race).
|
|
842
836
|
key_listener_stop_event = threading.Event()
|
|
843
|
-
|
|
837
|
+
handle, spawned = _key_listeners.acquire_listener(
|
|
844
838
|
key_listener_stop_event,
|
|
845
839
|
# Ctrl+X: command_runner installs a dynamic handler via
|
|
846
840
|
# _key_listeners.set_escape_handler() while shell commands
|
|
@@ -848,10 +842,11 @@ async def run_with_mcp(
|
|
|
848
842
|
on_escape=lambda: None,
|
|
849
843
|
on_cancel_agent=cancel_cb,
|
|
850
844
|
)
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
845
|
+
if spawned:
|
|
846
|
+
key_listener_handle = handle
|
|
847
|
+
else:
|
|
848
|
+
using_persistent_listener = True
|
|
849
|
+
_key_listeners.set_cancel_handler(cancel_cb)
|
|
855
850
|
|
|
856
851
|
result = await agent_task
|
|
857
852
|
run_success = True
|
|
@@ -868,22 +863,27 @@ async def run_with_mcp(
|
|
|
868
863
|
except asyncio.CancelledError:
|
|
869
864
|
run_response_text = ""
|
|
870
865
|
agent_task.cancel()
|
|
871
|
-
|
|
866
|
+
# Nested runs never drain: the pending steers belong to the outer
|
|
867
|
+
# run, whose own cancel path (or run end) handles them.
|
|
868
|
+
if not is_nested_run:
|
|
869
|
+
drain_pause_state_on_cancel()
|
|
872
870
|
except KeyboardInterrupt:
|
|
873
871
|
run_response_text = ""
|
|
874
872
|
if not agent_task.done():
|
|
875
873
|
agent_task.cancel()
|
|
876
|
-
|
|
874
|
+
if not is_nested_run:
|
|
875
|
+
drain_pause_state_on_cancel()
|
|
877
876
|
except Exception as e:
|
|
878
877
|
run_error = e
|
|
879
878
|
raise
|
|
880
879
|
finally:
|
|
881
|
-
|
|
882
|
-
|
|
880
|
+
if not is_nested_run:
|
|
881
|
+
try:
|
|
882
|
+
from code_puppy.tools import command_runner as _command_runner
|
|
883
883
|
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
884
|
+
_command_runner.clear_agent_cancel()
|
|
885
|
+
except Exception:
|
|
886
|
+
pass
|
|
887
887
|
try:
|
|
888
888
|
await on_agent_run_end(
|
|
889
889
|
agent_name=agent.name,
|
|
@@ -8,7 +8,6 @@ PhaseType = Literal[
|
|
|
8
8
|
"shutdown",
|
|
9
9
|
"invoke_agent",
|
|
10
10
|
"agent_exception",
|
|
11
|
-
"agent_retryable_exception",
|
|
12
11
|
"version_check",
|
|
13
12
|
"edit_file",
|
|
14
13
|
"create_file",
|
|
@@ -64,7 +63,6 @@ _callbacks: Dict[PhaseType, List[CallbackFunc]] = {
|
|
|
64
63
|
"shutdown": [],
|
|
65
64
|
"invoke_agent": [],
|
|
66
65
|
"agent_exception": [],
|
|
67
|
-
"agent_retryable_exception": [],
|
|
68
66
|
"version_check": [],
|
|
69
67
|
"edit_file": [],
|
|
70
68
|
"create_file": [],
|
|
@@ -330,23 +328,6 @@ async def on_agent_exception(exception: Exception, *args, **kwargs) -> List[Any]
|
|
|
330
328
|
return await _trigger_callbacks("agent_exception", exception, *args, **kwargs)
|
|
331
329
|
|
|
332
330
|
|
|
333
|
-
async def on_agent_retryable_exception(
|
|
334
|
-
exception: Exception, *args, **kwargs
|
|
335
|
-
) -> List[Any]:
|
|
336
|
-
"""Ask plugins whether an exception the core classifier rejected is retryable.
|
|
337
|
-
|
|
338
|
-
Fired from the main agent retry loop (``streaming_retry``) when
|
|
339
|
-
``should_retry_streaming`` says an exception is NOT transient. Plugins
|
|
340
|
-
receive ``(exception, model_name=..., attempt=..., max_attempts=...)`` and
|
|
341
|
-
may perform recovery work (e.g. refreshing an OAuth token) before
|
|
342
|
-
answering. Any truthy result opts the exception into the standard retry
|
|
343
|
-
schedule (delays, banner, error-log, attempt cap).
|
|
344
|
-
"""
|
|
345
|
-
return await _trigger_callbacks(
|
|
346
|
-
"agent_retryable_exception", exception, *args, **kwargs
|
|
347
|
-
)
|
|
348
|
-
|
|
349
|
-
|
|
350
331
|
async def on_version_check(*args, **kwargs) -> List[Any]:
|
|
351
332
|
return await _trigger_callbacks("version_check", *args, **kwargs)
|
|
352
333
|
|
|
@@ -440,15 +440,8 @@ class ClaudeCacheAsyncClient(httpx.AsyncClient):
|
|
|
440
440
|
if response.status_code == 400:
|
|
441
441
|
is_auth_error = await self._is_cloudflare_html_error(response)
|
|
442
442
|
if is_auth_error:
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
request_body = self._extract_body_bytes(request) or b""
|
|
446
|
-
logger.warning(
|
|
447
|
-
"Detected Cloudflare HTML 400 (cf-ray=%s, "
|
|
448
|
-
"request_bytes=%d, url=%s); attempting token refresh",
|
|
449
|
-
response.headers.get("cf-ray"),
|
|
450
|
-
len(request_body),
|
|
451
|
-
request.url.path,
|
|
443
|
+
logger.info(
|
|
444
|
+
"Detected Cloudflare 400 error (likely auth-related), attempting token refresh"
|
|
452
445
|
)
|
|
453
446
|
|
|
454
447
|
if is_auth_error:
|
|
@@ -148,6 +148,10 @@ def stop_run_ui() -> None:
|
|
|
148
148
|
# The UI outlives the run — just drop back to idle routing.
|
|
149
149
|
_run_active = False
|
|
150
150
|
_clear_status_row()
|
|
151
|
+
# Self-heal: if the REPL-lifetime listener died mid-run (its
|
|
152
|
+
# thread crashed, or a per-run listener replaced-then-stopped
|
|
153
|
+
# it), typing at the idle prompt would be dead forever.
|
|
154
|
+
_ensure_persistent_listener_locked()
|
|
151
155
|
return
|
|
152
156
|
editor = _editor
|
|
153
157
|
_editor = None
|
|
@@ -403,17 +407,52 @@ def _spawn_persistent_listener() -> None:
|
|
|
403
407
|
from code_puppy.agents import _key_listeners
|
|
404
408
|
except ImportError:
|
|
405
409
|
return # no listener infra: prompt still works via nothing-to-feed
|
|
406
|
-
if _key_listeners.get_active_handle() is not None:
|
|
407
|
-
return # someone else owns stdin already
|
|
408
410
|
stop_event = threading.Event()
|
|
409
|
-
|
|
410
|
-
|
|
411
|
+
# Atomic reuse-or-spawn: if someone else already owns stdin we back
|
|
412
|
+
# off (spawned=False) and deliberately do NOT record their handle as
|
|
413
|
+
# ours — stop_persistent_ui must never stop a listener it didn't spawn.
|
|
414
|
+
handle, spawned = _key_listeners.acquire_listener(
|
|
415
|
+
stop_event, on_escape=lambda: None
|
|
416
|
+
)
|
|
417
|
+
if handle is None or not spawned:
|
|
411
418
|
return
|
|
412
|
-
_key_listeners.set_active_handle(handle)
|
|
413
419
|
with _lock:
|
|
414
420
|
_listener_handle = handle
|
|
415
421
|
|
|
416
422
|
|
|
423
|
+
def _ensure_persistent_listener_locked() -> None:
|
|
424
|
+
"""Respawn the persistent listener if it died. Caller holds ``_lock``.
|
|
425
|
+
|
|
426
|
+
Never raises — this runs on ``finally`` teardown paths.
|
|
427
|
+
"""
|
|
428
|
+
global _listener_handle
|
|
429
|
+
handle = _listener_handle
|
|
430
|
+
if (
|
|
431
|
+
handle is not None
|
|
432
|
+
and handle.thread.is_alive()
|
|
433
|
+
and not handle.stop_event.is_set()
|
|
434
|
+
):
|
|
435
|
+
return # healthy
|
|
436
|
+
try:
|
|
437
|
+
from code_puppy.agents import _key_listeners
|
|
438
|
+
except ImportError:
|
|
439
|
+
return
|
|
440
|
+
try:
|
|
441
|
+
# Drop the stale registration (if it's still ours) so
|
|
442
|
+
# acquire_listener doesn't refuse to spawn over a corpse.
|
|
443
|
+
if handle is not None and _key_listeners.get_active_handle() is handle:
|
|
444
|
+
_key_listeners.set_active_handle(None)
|
|
445
|
+
_listener_handle = None
|
|
446
|
+
stop_event = threading.Event()
|
|
447
|
+
new_handle, spawned = _key_listeners.acquire_listener(
|
|
448
|
+
stop_event, on_escape=lambda: None
|
|
449
|
+
)
|
|
450
|
+
if new_handle is not None and spawned:
|
|
451
|
+
_listener_handle = new_handle
|
|
452
|
+
except Exception:
|
|
453
|
+
logger.debug("persistent listener respawn failed", exc_info=True)
|
|
454
|
+
|
|
455
|
+
|
|
417
456
|
# =============================================================================
|
|
418
457
|
# Slash-command consumer (Phase 5)
|
|
419
458
|
# =============================================================================
|
|
@@ -156,10 +156,6 @@ claude_code_oauth/
|
|
|
156
156
|
|
|
157
157
|
- The plugin assumes Anthropic continues to expose the shared `claude-cli` OAuth client
|
|
158
158
|
- Tokens are refreshed on subsequent API calls if the service returns refresh tokens
|
|
159
|
-
- Auth failures (401/403, or Cloudflare HTML 400s) that escape the HTTP client's
|
|
160
|
-
per-request refresh trigger an automatic token refresh and ride the main agent
|
|
161
|
-
retry loop via the `agent_retryable_exception` hook (see `auth_retry.py`) —
|
|
162
|
-
same delays and attempt cap as a 429, so users aren't interrupted
|
|
163
159
|
- Models are prefixed with `claude-code-` to avoid collisions with other Anthropic models
|
|
164
160
|
|
|
165
161
|
## Contributing
|
{code_puppy-0.0.593 → code_puppy-0.0.595}/code_puppy/plugins/claude_code_oauth/register_callbacks.py
RENAMED
|
@@ -23,7 +23,6 @@ from code_puppy.provider_identity import (
|
|
|
23
23
|
)
|
|
24
24
|
|
|
25
25
|
from ..oauth_puppy_html import oauth_failure_html, oauth_success_html
|
|
26
|
-
from .auth_retry import handle_retryable_exception, register_runtime_token_updater
|
|
27
26
|
from .config import CLAUDE_CODE_OAUTH_CONFIG, get_token_storage_path
|
|
28
27
|
from .fast_mode import (
|
|
29
28
|
FAST_SETTING_KEY,
|
|
@@ -457,9 +456,6 @@ def _create_claude_code_model(model_name: str, model_config: Dict, config: Dict)
|
|
|
457
456
|
custom_endpoint["api_key"] = access_token
|
|
458
457
|
|
|
459
458
|
client.set_token_update_callback(_update_runtime_token)
|
|
460
|
-
# Also track the updater so agent-level auth-retry (auth_retry.py) can
|
|
461
|
-
# broadcast a refreshed token into this live client before re-running.
|
|
462
|
-
register_runtime_token_updater(_update_runtime_token)
|
|
463
459
|
patch_anthropic_client_messages(anthropic_client)
|
|
464
460
|
# Fast mode wrapper sits outside cache-control injector and re-reads
|
|
465
461
|
# the setting on every call so /claude-code-fast takes effect live.
|
|
@@ -548,7 +544,6 @@ async def _on_agent_run_end(
|
|
|
548
544
|
logger.debug("Error stopping token refresh heartbeat: %s", exc)
|
|
549
545
|
|
|
550
546
|
|
|
551
|
-
register_callback("agent_retryable_exception", handle_retryable_exception)
|
|
552
547
|
register_callback("custom_command_help", _custom_help)
|
|
553
548
|
register_callback("custom_command", _handle_custom_command)
|
|
554
549
|
register_callback("register_model_type", _register_model_types)
|
|
@@ -26,14 +26,6 @@ from .config import (
|
|
|
26
26
|
TOKEN_REFRESH_BUFFER_SECONDS = 300
|
|
27
27
|
MIN_REFRESH_BUFFER_SECONDS = 30
|
|
28
28
|
|
|
29
|
-
# Cooldown for *forced* refreshes (seconds). Every refresh-token exchange
|
|
30
|
-
# rotates the refresh token; hammering the endpoint during a flappy episode
|
|
31
|
-
# (e.g. repeated Cloudflare 400s that a new token can't cure anyway) burns
|
|
32
|
-
# through rotations for nothing and risks invalidating the token family.
|
|
33
|
-
# If the stored tokens were refreshed within this window and are still
|
|
34
|
-
# valid, force=True short-circuits to the existing access token.
|
|
35
|
-
FORCE_REFRESH_COOLDOWN_SECONDS = 30
|
|
36
|
-
|
|
37
29
|
logger = logging.getLogger(__name__)
|
|
38
30
|
|
|
39
31
|
|
|
@@ -221,19 +213,6 @@ def refresh_access_token(force: bool = False) -> Optional[str]:
|
|
|
221
213
|
if not force and not is_token_expired(tokens):
|
|
222
214
|
return tokens.get("access_token")
|
|
223
215
|
|
|
224
|
-
# Forced-refresh cooldown: a token minted seconds ago is as fresh as a
|
|
225
|
-
# new exchange would produce. Skip the rotation and reuse it.
|
|
226
|
-
if force and tokens.get("access_token") and not is_token_expired(tokens):
|
|
227
|
-
seconds_since_refresh = time.time() - float(tokens.get("refreshed_at") or 0)
|
|
228
|
-
if seconds_since_refresh < FORCE_REFRESH_COOLDOWN_SECONDS:
|
|
229
|
-
logger.info(
|
|
230
|
-
"Skipping forced token refresh (last refresh %.0fs ago, "
|
|
231
|
-
"cooldown %ds); reusing current access token",
|
|
232
|
-
seconds_since_refresh,
|
|
233
|
-
FORCE_REFRESH_COOLDOWN_SECONDS,
|
|
234
|
-
)
|
|
235
|
-
return tokens.get("access_token")
|
|
236
|
-
|
|
237
216
|
refresh_token = tokens.get("refresh_token")
|
|
238
217
|
if not refresh_token:
|
|
239
218
|
logger.debug("No refresh_token available")
|
|
@@ -280,7 +259,6 @@ def refresh_access_token(force: bool = False) -> Optional[str]:
|
|
|
280
259
|
if expires_in_value is not None:
|
|
281
260
|
tokens["expires_in"] = expires_in_value
|
|
282
261
|
tokens["expires_at"] = _calculate_expires_at(expires_in_value)
|
|
283
|
-
tokens["refreshed_at"] = time.time()
|
|
284
262
|
if save_tokens(tokens):
|
|
285
263
|
update_claude_code_model_tokens(tokens["access_token"])
|
|
286
264
|
return tokens["access_token"]
|