code-puppy 0.0.562__tar.gz → 0.0.563__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.562 → code_puppy-0.0.563}/PKG-INFO +1 -1
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/agents/event_stream_handler.py +92 -21
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/agents/run_stats.py +276 -4
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/set_menu_catalog.py +14 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/config.py +45 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/messaging/renderers.py +101 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/messaging/rich_renderer.py +170 -13
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/messaging/spinner/__init__.py +14 -2
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/tools/display.py +5 -3
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/tools/file_operations.py +3 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/tools/subagent_invocation.py +50 -10
- {code_puppy-0.0.562 → code_puppy-0.0.563}/pyproject.toml +1 -1
- {code_puppy-0.0.562 → code_puppy-0.0.563}/.gitignore +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/LICENSE +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/README.md +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/__main__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/agents/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/agents/_builder.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/agents/_compaction.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/agents/_diagnostics.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/agents/_history.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/agents/_key_listeners.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/agents/_non_streaming_render.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/agents/_run_signals.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/agents/_runtime.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/agents/_steer_processor.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/agents/agent_code_puppy.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/agents/agent_creator_agent.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/agents/agent_helios.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/agents/agent_manager.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/agents/agent_planning.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/agents/agent_qa_kitten.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/agents/base_agent.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/agents/json_agent.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/agents/smooth_stream.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/agents/subagent_stream_handler.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/callbacks.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/chatgpt_codex_client.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/claude_cache_client.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/cli_runner.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/add_model_menu.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/agent_menu.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/attachments.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/autosave_menu.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/clipboard.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/colors_menu.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/command_handler.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/command_registry.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/config_apply.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/config_commands.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/core_commands.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/diff_menu.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/file_index.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/file_path_completion.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/judges_menu.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/load_context_completion.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/mcp/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/mcp/base.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/mcp/catalog_server_installer.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/mcp/custom_server_form.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/mcp/custom_server_installer.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/mcp/edit_command.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/mcp/handler.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/mcp/help_command.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/mcp/install_command.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/mcp/install_menu.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/mcp/list_command.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/mcp/logs_command.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/mcp/remove_command.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/mcp/restart_command.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/mcp/search_command.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/mcp/silence_warning_command.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/mcp/start_all_command.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/mcp/start_command.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/mcp/status_command.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/mcp/stop_all_command.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/mcp/stop_command.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/mcp/utils.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/mcp/wizard_utils.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/mcp_binding_menu.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/mcp_completion.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/model_picker_completion.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/model_settings_menu.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/onboarding_slides.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/onboarding_wizard.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/pagination.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/pin_command_completion.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/prompt_toolkit_completion.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/session_commands.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/set_menu.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/set_menu_render.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/set_menu_schema.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/set_menu_settings.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/set_menu_shims.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/set_menu_values.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/shell_passthrough.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/skills_completion.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/uc_menu.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/utils.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/command_line/wiggum_state.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/error_logging.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/gemini_code_assist.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/gemini_model.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/hook_engine/README.md +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/hook_engine/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/hook_engine/aliases.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/hook_engine/engine.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/hook_engine/executor.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/hook_engine/matcher.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/hook_engine/models.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/hook_engine/registry.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/hook_engine/validator.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/http_utils.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/keymap.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/list_filtering.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/main.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/mcp_/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/mcp_/agent_bindings.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/mcp_/async_lifecycle.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/mcp_/blocking_startup.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/mcp_/captured_stdio_server.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/mcp_/circuit_breaker.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/mcp_/config_wizard.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/mcp_/dashboard.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/mcp_/error_isolation.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/mcp_/examples/retry_example.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/mcp_/health_monitor.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/mcp_/managed_server.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/mcp_/manager.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/mcp_/mcp_logs.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/mcp_/registry.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/mcp_/retry_manager.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/mcp_/server_registry_catalog.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/mcp_/status_tracker.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/mcp_/system_tools.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/mcp_prompts/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/mcp_prompts/hook_creator.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/messaging/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/messaging/bus.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/messaging/commands.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/messaging/markdown_patches.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/messaging/message_queue.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/messaging/messages.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/messaging/pause_controller.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/messaging/queue_console.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/messaging/spinner/console_spinner.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/messaging/spinner/spinner_base.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/messaging/subagent_console.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/model_descriptions.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/model_factory.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/model_switching.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/model_utils.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/models.json +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/models_dev_api.json +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/models_dev_parser.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/agent_skills/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/agent_skills/config.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/agent_skills/discovery.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/agent_skills/downloader.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/agent_skills/enabled_skills.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/agent_skills/installer.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/agent_skills/metadata.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/agent_skills/prompt_builder.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/agent_skills/register_callbacks.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/agent_skills/remote_catalog.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/agent_skills/skill_catalog.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/agent_skills/skill_commands.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/agent_skills/skills_install_menu.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/agent_skills/skills_menu.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/agent_steering/README.md +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/agent_steering/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/agent_steering/line_editor.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/agent_steering/register_callbacks.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/agent_steering/steering_prompt.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/aws_bedrock/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/aws_bedrock/config.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/aws_bedrock/register_callbacks.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/aws_bedrock/utils.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/azure_foundry/README.md +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/azure_foundry/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/azure_foundry/config.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/azure_foundry/discovery.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/azure_foundry/register_callbacks.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/azure_foundry/token.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/azure_foundry/utils.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/chatgpt_oauth/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/chatgpt_oauth/config.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/chatgpt_oauth/oauth_flow.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/chatgpt_oauth/register_callbacks.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/chatgpt_oauth/test_plugin.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/chatgpt_oauth/utils.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/claude_code_hooks/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/claude_code_hooks/config.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/claude_code_hooks/register_callbacks.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/claude_code_oauth/README.md +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/claude_code_oauth/SETUP.md +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/claude_code_oauth/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/claude_code_oauth/config.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/claude_code_oauth/fast_mode.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/claude_code_oauth/prompt_handler.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/claude_code_oauth/register_callbacks.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/claude_code_oauth/test_fast_mode.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/claude_code_oauth/test_plugin.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/claude_code_oauth/token_refresh_heartbeat.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/claude_code_oauth/utils.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/config.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/context_indicator/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/context_indicator/register_callbacks.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/context_indicator/usage.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/copilot_auth/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/copilot_auth/config.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/copilot_auth/reasoning_client.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/copilot_auth/register_callbacks.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/copilot_auth/utils.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/customizable_commands/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/customizable_commands/register_callbacks.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/dbos_durable_exec/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/dbos_durable_exec/cancel.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/dbos_durable_exec/commands.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/dbos_durable_exec/config.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/dbos_durable_exec/lifecycle.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/dbos_durable_exec/register_callbacks.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/dbos_durable_exec/runtime.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/dbos_durable_exec/workflow_ids.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/dbos_durable_exec/wrapper.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/destructive_command_guard/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/destructive_command_guard/detector.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/destructive_command_guard/register_callbacks.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/emoji_filter/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/emoji_filter/config.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/emoji_filter/register_callbacks.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/emoji_filter/stripper.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/example_custom_command/README.md +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/example_custom_command/register_callbacks.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/file_permission_handler/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/file_permission_handler/register_callbacks.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/force_push_guard/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/force_push_guard/detector.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/force_push_guard/register_callbacks.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/force_push_guard/test_detector.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/frontend_emitter/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/frontend_emitter/emitter.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/frontend_emitter/register_callbacks.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/frontend_emitter/session_context.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/hook_creator/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/hook_creator/register_callbacks.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/hook_manager/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/hook_manager/config.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/hook_manager/hooks_menu.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/hook_manager/register_callbacks.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/oauth_puppy_html.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/obsidian_agent/README.md +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/obsidian_agent/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/obsidian_agent/agent_obsidian.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/obsidian_agent/register_callbacks.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/ollama/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/ollama/register_callbacks.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/ollama_setup/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/ollama_setup/completer.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/ollama_setup/register_callbacks.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/plugin_list/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/plugin_list/plugins_menu.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/plugin_list/register_callbacks.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/pop_command/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/pop_command/register_callbacks.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/prompt_newline/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/prompt_newline/config.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/prompt_newline/register_callbacks.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/prune/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/prune/prune_menu.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/prune/prune_model.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/prune/prune_render.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/prune/register_callbacks.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/puppy_kennel/README.md +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/puppy_kennel/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/puppy_kennel/commands.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/puppy_kennel/config.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/puppy_kennel/kennel.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/puppy_kennel/packer.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/puppy_kennel/recorder.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/puppy_kennel/register_callbacks.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/puppy_kennel/retriever.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/puppy_kennel/schema.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/puppy_kennel/state.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/puppy_kennel/tools.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/puppy_kennel/wings.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/review_pr/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/review_pr/register_callbacks.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/shell_safety/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/shell_safety/agent_shell_safety.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/shell_safety/command_cache.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/shell_safety/register_callbacks.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/statusline/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/statusline/config.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/statusline/payload.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/statusline/prompt_patch.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/statusline/register_callbacks.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/statusline/runner.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/statusline/statusline_command.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/switch_agent_resume/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/switch_agent_resume/register_callbacks.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/synthetic_status/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/synthetic_status/register_callbacks.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/synthetic_status/status_api.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/theme/README.md +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/theme/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/theme/bundled_palettes.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/theme/content_styles.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/theme/osc_palette.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/theme/picker.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/theme/register_callbacks.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/theme/rich_themes.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/theme/themes.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/token_ratio_learner/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/token_ratio_learner/ratios.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/token_ratio_learner/register_callbacks.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/universal_constructor/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/universal_constructor/models.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/universal_constructor/register_callbacks.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/universal_constructor/registry.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/universal_constructor/sandbox.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/wide_completion_menu/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/wide_completion_menu/register_callbacks.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/wiggum/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/wiggum/judge.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/wiggum/judge_config.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/wiggum/register_callbacks.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/plugins/wiggum/state.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/provider_credentials.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/provider_identity.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/pydantic_patches.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/reopenable_async_client.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/round_robin_model.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/session_storage.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/status_display.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/summarization_agent.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/terminal_utils.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/tools/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/tools/agent_tools.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/tools/ask_user_question/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/tools/ask_user_question/constants.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/tools/ask_user_question/demo_tui.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/tools/ask_user_question/handler.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/tools/ask_user_question/models.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/tools/ask_user_question/registration.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/tools/ask_user_question/renderers.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/tools/ask_user_question/terminal_ui.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/tools/ask_user_question/theme.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/tools/ask_user_question/tui_loop.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/tools/browser/__init__.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/tools/browser/browser_control.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/tools/browser/browser_interactions.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/tools/browser/browser_locators.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/tools/browser/browser_manager.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/tools/browser/browser_navigation.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/tools/browser/browser_screenshot.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/tools/browser/browser_scripts.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/tools/browser/browser_workflows.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/tools/command_runner.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/tools/common.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/tools/file_modifications.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/tools/image_tools.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/tools/model_tools.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/tools/skills_tools.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/tools/subagent_context.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/tools/tools_content.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/tools/universal_constructor.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/uvx_detection.py +0 -0
- {code_puppy-0.0.562 → code_puppy-0.0.563}/code_puppy/version_checker.py +0 -0
|
@@ -25,7 +25,12 @@ from code_puppy.agents.smooth_stream import (
|
|
|
25
25
|
make_smooth_termflow_writer,
|
|
26
26
|
make_thinking_smoother,
|
|
27
27
|
)
|
|
28
|
-
from code_puppy.config import
|
|
28
|
+
from code_puppy.config import (
|
|
29
|
+
get_banner_color,
|
|
30
|
+
get_output_level,
|
|
31
|
+
get_subagent_verbose,
|
|
32
|
+
get_suppress_thinking_messages,
|
|
33
|
+
)
|
|
29
34
|
from code_puppy.messaging.spinner import pause_all_spinners, resume_all_spinners
|
|
30
35
|
from code_puppy.tools.subagent_context import is_subagent
|
|
31
36
|
|
|
@@ -86,12 +91,41 @@ def get_streaming_console() -> Console:
|
|
|
86
91
|
def _should_suppress_output() -> bool:
|
|
87
92
|
"""Check if sub-agent output should be suppressed.
|
|
88
93
|
|
|
94
|
+
In ``high`` output mode, sub-agent output is never suppressed.
|
|
95
|
+
|
|
89
96
|
Returns:
|
|
90
97
|
True if we're in a sub-agent context and verbose mode is disabled.
|
|
91
98
|
"""
|
|
99
|
+
if get_output_level() == "high":
|
|
100
|
+
return False
|
|
92
101
|
return is_subagent() and not get_subagent_verbose()
|
|
93
102
|
|
|
94
103
|
|
|
104
|
+
def _suppress_thinking_stream() -> bool:
|
|
105
|
+
"""Return True if thinking banners/content should be hidden.
|
|
106
|
+
|
|
107
|
+
Thinking is suppressed in ``low`` output mode (collapsed to a peek
|
|
108
|
+
by the RichConsoleRenderer) or when the user has explicitly set
|
|
109
|
+
``suppress_thinking_messages``.
|
|
110
|
+
|
|
111
|
+
In ``high`` output mode, thinking is *never* suppressed -- the user
|
|
112
|
+
explicitly asked for maximum visibility.
|
|
113
|
+
"""
|
|
114
|
+
level = get_output_level()
|
|
115
|
+
if level == "high":
|
|
116
|
+
return False
|
|
117
|
+
return level == "low" or get_suppress_thinking_messages()
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def _suppress_tool_progress() -> bool:
|
|
121
|
+
"""Return True if tool-call progress counters should be hidden.
|
|
122
|
+
|
|
123
|
+
In ``low`` mode, the shell-start peek in the RichConsoleRenderer is
|
|
124
|
+
sufficient; the streaming token counter is noise.
|
|
125
|
+
"""
|
|
126
|
+
return get_output_level() == "low"
|
|
127
|
+
|
|
128
|
+
|
|
95
129
|
async def event_stream_handler(
|
|
96
130
|
ctx: RunContext,
|
|
97
131
|
events: AsyncIterable[Any],
|
|
@@ -130,7 +164,9 @@ async def event_stream_handler(
|
|
|
130
164
|
banner_printed: set[int] = set() # Track if banner was already printed
|
|
131
165
|
token_count: dict[int, int] = {} # Track token count per text/tool part
|
|
132
166
|
tool_names: dict[int, str] = {} # Track tool name per tool part index
|
|
167
|
+
tool_args_buffer: dict[int, str] = {} # Accumulate raw tool-call args JSON
|
|
133
168
|
did_stream_anything = False # Track if we streamed any content
|
|
169
|
+
is_high_mode = get_output_level() == "high"
|
|
134
170
|
|
|
135
171
|
# Termflow streaming state for text parts
|
|
136
172
|
termflow_parsers: dict[int, TermflowParser] = {}
|
|
@@ -188,6 +224,7 @@ async def event_stream_handler(
|
|
|
188
224
|
console.print() # Newline before banner
|
|
189
225
|
# Bold banner with configurable color and lightning bolt
|
|
190
226
|
thinking_color = get_banner_color("thinking")
|
|
227
|
+
|
|
191
228
|
console.print(
|
|
192
229
|
Text.from_markup(
|
|
193
230
|
f"[bold white on {thinking_color}] THINKING [/bold white on {thinking_color}] [dim]\u26a1 "
|
|
@@ -267,9 +304,11 @@ async def event_stream_handler(
|
|
|
267
304
|
streaming_parts.add(event.index)
|
|
268
305
|
thinking_parts.add(event.index)
|
|
269
306
|
# If there's initial content, print banner + content now
|
|
307
|
+
# (unless thinking is suppressed by output level or toggle).
|
|
270
308
|
if part.content and part.content.strip():
|
|
271
|
-
|
|
272
|
-
|
|
309
|
+
if not _suppress_thinking_stream():
|
|
310
|
+
await _print_thinking_banner()
|
|
311
|
+
_emit_thinking(event.index, part.content)
|
|
273
312
|
banner_printed.add(event.index)
|
|
274
313
|
elif isinstance(part, TextPart):
|
|
275
314
|
streaming_parts.add(event.index)
|
|
@@ -287,6 +326,7 @@ async def event_stream_handler(
|
|
|
287
326
|
streaming_parts.add(event.index)
|
|
288
327
|
tool_parts.add(event.index)
|
|
289
328
|
token_count[event.index] = 0 # Initialize token counter
|
|
329
|
+
tool_args_buffer[event.index] = "" # Accumulate JSON args
|
|
290
330
|
# Capture tool name from the start event
|
|
291
331
|
tool_names[event.index] = part.tool_name or ""
|
|
292
332
|
# Track tool name for display
|
|
@@ -336,10 +376,12 @@ async def event_stream_handler(
|
|
|
336
376
|
else:
|
|
337
377
|
# For thinking parts, stream smoothly (dim) via a
|
|
338
378
|
# rate-limited buffer so bursty deltas don't stutter.
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
379
|
+
# Gate on output level / suppress_thinking toggle.
|
|
380
|
+
if not _suppress_thinking_stream():
|
|
381
|
+
if event.index not in banner_printed:
|
|
382
|
+
await _print_thinking_banner()
|
|
383
|
+
banner_printed.add(event.index)
|
|
384
|
+
_emit_thinking(event.index, delta.content_delta)
|
|
343
385
|
elif isinstance(delta, ToolCallPartDelta):
|
|
344
386
|
# For tool calls, estimate tokens from args_delta content
|
|
345
387
|
# args_delta contains the streaming JSON arguments
|
|
@@ -348,6 +390,10 @@ async def event_stream_handler(
|
|
|
348
390
|
# Same 2.5 chars/token heuristic as BaseAgent and file_operations
|
|
349
391
|
estimated_tokens = max(1, math.floor(len(args_delta) / 2.5))
|
|
350
392
|
token_count[event.index] += estimated_tokens
|
|
393
|
+
# Accumulate raw args JSON for high-mode display.
|
|
394
|
+
tool_args_buffer[event.index] = (
|
|
395
|
+
tool_args_buffer.get(event.index, "") + args_delta
|
|
396
|
+
)
|
|
351
397
|
else:
|
|
352
398
|
# Even empty deltas count as activity
|
|
353
399
|
token_count[event.index] += 1
|
|
@@ -359,20 +405,23 @@ async def event_stream_handler(
|
|
|
359
405
|
tool_names.get(event.index, "") + tool_name_delta
|
|
360
406
|
)
|
|
361
407
|
|
|
362
|
-
# Use stored tool name for display
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
408
|
+
# Use stored tool name for display.
|
|
409
|
+
# In low mode, skip the progress counter — the
|
|
410
|
+
# RichConsoleRenderer peek is sufficient.
|
|
411
|
+
if not _suppress_tool_progress():
|
|
412
|
+
tool_name = tool_names.get(event.index, "")
|
|
413
|
+
count = token_count[event.index]
|
|
414
|
+
# Display with tool wrench icon and tool name
|
|
415
|
+
if tool_name:
|
|
416
|
+
console.print(
|
|
417
|
+
f" \U0001f527 Calling {tool_name}... {count} token(s) ",
|
|
418
|
+
end="\r",
|
|
419
|
+
)
|
|
420
|
+
else:
|
|
421
|
+
console.print(
|
|
422
|
+
f" \U0001f527 Calling tool... {count} token(s) ",
|
|
423
|
+
end="\r",
|
|
424
|
+
)
|
|
376
425
|
|
|
377
426
|
# PartEndEvent - finish the streaming with a newline
|
|
378
427
|
elif isinstance(event, PartEndEvent):
|
|
@@ -417,6 +466,27 @@ async def event_stream_handler(
|
|
|
417
466
|
elif event.index in tool_parts:
|
|
418
467
|
# Clear the chunk counter line by printing spaces and returning
|
|
419
468
|
console.print(" " * 50, end="\r")
|
|
469
|
+
# In high mode, dump the full tool call arguments so the
|
|
470
|
+
# user can see exactly what the model sent to the tool.
|
|
471
|
+
if is_high_mode:
|
|
472
|
+
tool_name = tool_names.get(event.index, "tool")
|
|
473
|
+
raw_args = tool_args_buffer.get(event.index, "")
|
|
474
|
+
if raw_args:
|
|
475
|
+
# Pretty-print the JSON if possible.
|
|
476
|
+
import json as _json
|
|
477
|
+
|
|
478
|
+
try:
|
|
479
|
+
parsed = _json.loads(raw_args)
|
|
480
|
+
formatted = _json.dumps(
|
|
481
|
+
parsed, indent=2, ensure_ascii=False
|
|
482
|
+
)
|
|
483
|
+
except (ValueError, TypeError):
|
|
484
|
+
formatted = raw_args
|
|
485
|
+
console.print(
|
|
486
|
+
f"[dim] tool_call {escape(tool_name)} args:[/dim]"
|
|
487
|
+
)
|
|
488
|
+
for arg_line in formatted.splitlines():
|
|
489
|
+
console.print(f"[dim] {escape(arg_line)}[/dim]")
|
|
420
490
|
# For thinking parts, drain the smoother then print newline
|
|
421
491
|
elif event.index in thinking_parts:
|
|
422
492
|
smoother = thinking_smoothers.pop(event.index, None)
|
|
@@ -429,6 +499,7 @@ async def event_stream_handler(
|
|
|
429
499
|
# Clean up token count and tool names
|
|
430
500
|
token_count.pop(event.index, None)
|
|
431
501
|
tool_names.pop(event.index, None)
|
|
502
|
+
tool_args_buffer.pop(event.index, None)
|
|
432
503
|
# Clean up all tracking sets
|
|
433
504
|
streaming_parts.discard(event.index)
|
|
434
505
|
thinking_parts.discard(event.index)
|
|
@@ -70,12 +70,16 @@ class AgentRunStats:
|
|
|
70
70
|
_last_token_time: float = 0.0
|
|
71
71
|
_gen_seconds: float = 0.0
|
|
72
72
|
_output_tokens: int = 0
|
|
73
|
+
_current_model_name: str = ""
|
|
73
74
|
|
|
74
75
|
# Snapshot of the most-recently-finished cycle. Used as a fallback so
|
|
75
76
|
# consumers (telemetry, future displays) have something stable to read
|
|
76
77
|
# between cycles instead of seeing zeros.
|
|
77
78
|
_last_ttft_seconds: float = 0.0
|
|
78
79
|
_last_gen_tps: float = 0.0
|
|
80
|
+
_last_output_tokens: int = 0
|
|
81
|
+
_last_gen_seconds: float = 0.0
|
|
82
|
+
_last_model_name: str = ""
|
|
79
83
|
|
|
80
84
|
# --------------- conversation-wide aggregates ---------------
|
|
81
85
|
# Summed across every model call in the session so we can report
|
|
@@ -87,7 +91,7 @@ class AgentRunStats:
|
|
|
87
91
|
|
|
88
92
|
# ----------------- API -----------------
|
|
89
93
|
@classmethod
|
|
90
|
-
def mark_request_start(cls) -> None:
|
|
94
|
+
def mark_request_start(cls, model_name: str = "") -> None:
|
|
91
95
|
"""Mark T0 = true request-start (called by ``agent_run_start`` hook).
|
|
92
96
|
|
|
93
97
|
Resets per-cycle counters but preserves conversation-wide aggregates
|
|
@@ -99,6 +103,7 @@ class AgentRunStats:
|
|
|
99
103
|
cls._last_token_time = 0.0
|
|
100
104
|
cls._gen_seconds = 0.0
|
|
101
105
|
cls._output_tokens = 0
|
|
106
|
+
cls._current_model_name = model_name
|
|
102
107
|
|
|
103
108
|
@classmethod
|
|
104
109
|
def record_output_tokens(cls, tokens: int) -> None:
|
|
@@ -127,7 +132,9 @@ class AgentRunStats:
|
|
|
127
132
|
cls._output_tokens += int(tokens)
|
|
128
133
|
|
|
129
134
|
@classmethod
|
|
130
|
-
def snapshot_cycle_into_aggregates(
|
|
135
|
+
def snapshot_cycle_into_aggregates(
|
|
136
|
+
cls,
|
|
137
|
+
) -> None:
|
|
131
138
|
"""Fold the just-finished cycle into conversation-wide aggregates.
|
|
132
139
|
|
|
133
140
|
Called by the ``agent_run_end`` hook so the auto-save line reflects
|
|
@@ -136,22 +143,46 @@ class AgentRunStats:
|
|
|
136
143
|
starts cleanly.
|
|
137
144
|
"""
|
|
138
145
|
with cls._lock:
|
|
146
|
+
cls._last_model_name = cls._current_model_name
|
|
139
147
|
if cls._first_token_time > 0.0 and cls._stream_start_time > 0.0:
|
|
140
148
|
ttft = cls._first_token_time - cls._stream_start_time
|
|
141
149
|
if ttft > 0:
|
|
142
150
|
cls._last_ttft_seconds = ttft
|
|
143
151
|
cls._total_ttft_seconds += ttft
|
|
144
152
|
cls._ttft_sample_count += 1
|
|
153
|
+
cls._last_output_tokens = cls._output_tokens
|
|
154
|
+
cls._last_gen_seconds = cls._gen_seconds
|
|
145
155
|
if cls._output_tokens > 0 and cls._gen_seconds > 0:
|
|
146
156
|
cls._last_gen_tps = cls._output_tokens / cls._gen_seconds
|
|
147
157
|
cls._total_output_tokens += cls._output_tokens
|
|
148
158
|
cls._total_gen_seconds += cls._gen_seconds
|
|
159
|
+
else:
|
|
160
|
+
cls._last_output_tokens = 0
|
|
161
|
+
cls._last_gen_seconds = 0.0
|
|
162
|
+
|
|
149
163
|
# Zero per-cycle state so the next run starts cleanly.
|
|
150
164
|
cls._stream_start_time = 0.0
|
|
151
165
|
cls._first_token_time = 0.0
|
|
152
166
|
cls._last_token_time = 0.0
|
|
153
167
|
cls._gen_seconds = 0.0
|
|
154
168
|
cls._output_tokens = 0
|
|
169
|
+
cls._current_model_name = ""
|
|
170
|
+
|
|
171
|
+
@classmethod
|
|
172
|
+
def get_last_cycle_stats(cls) -> dict:
|
|
173
|
+
"""Return a snapshot of the most-recently-completed cycle.
|
|
174
|
+
|
|
175
|
+
Keys: ``model``, ``ttft_seconds``, ``gen_tps``, ``gen_seconds``,
|
|
176
|
+
``output_tokens``.
|
|
177
|
+
"""
|
|
178
|
+
with cls._lock:
|
|
179
|
+
return {
|
|
180
|
+
"model": cls._last_model_name,
|
|
181
|
+
"ttft_seconds": cls._last_ttft_seconds,
|
|
182
|
+
"gen_tps": cls._last_gen_tps,
|
|
183
|
+
"gen_seconds": cls._last_gen_seconds,
|
|
184
|
+
"output_tokens": cls._last_output_tokens,
|
|
185
|
+
}
|
|
155
186
|
|
|
156
187
|
@classmethod
|
|
157
188
|
def reset_cycle_state(cls) -> None:
|
|
@@ -166,8 +197,12 @@ class AgentRunStats:
|
|
|
166
197
|
cls._last_token_time = 0.0
|
|
167
198
|
cls._gen_seconds = 0.0
|
|
168
199
|
cls._output_tokens = 0
|
|
200
|
+
cls._current_model_name = ""
|
|
169
201
|
cls._last_ttft_seconds = 0.0
|
|
170
202
|
cls._last_gen_tps = 0.0
|
|
203
|
+
cls._last_output_tokens = 0
|
|
204
|
+
cls._last_gen_seconds = 0.0
|
|
205
|
+
cls._last_model_name = ""
|
|
171
206
|
|
|
172
207
|
@classmethod
|
|
173
208
|
def reset_conversation_stats(cls) -> None:
|
|
@@ -229,6 +264,226 @@ class AgentRunStats:
|
|
|
229
264
|
return " | ".join(parts)
|
|
230
265
|
|
|
231
266
|
|
|
267
|
+
# ---------------------------------------------------------------------------
|
|
268
|
+
# High output-mode per-turn stats rendering
|
|
269
|
+
# ---------------------------------------------------------------------------
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
# Line threshold above which an informational footer is shown in high mode.
|
|
273
|
+
# This is NOT a truncation gate — high mode always shows the full result.
|
|
274
|
+
_HIGH_MODE_RESULT_FOOTER_THRESHOLD = 50
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
# Tool names whose response has already been rendered inline (streamed or
|
|
278
|
+
# via display_non_streamed_result) and should NOT be dumped again.
|
|
279
|
+
_ALREADY_RENDERED_TOOLS = frozenset({"invoke_agent", "invoke_agent_with_model"})
|
|
280
|
+
|
|
281
|
+
# Tools whose output is already rendered by the rich_renderer via MessageBus
|
|
282
|
+
# messages (FileContentMessage, DiffMessage, GrepResultMessage, etc.).
|
|
283
|
+
# High-mode metadata annotations are already shown inline by the renderer,
|
|
284
|
+
# so dumping the tool result body again would be noisy redundancy.
|
|
285
|
+
_TOOLS_WITH_RENDERER = frozenset(
|
|
286
|
+
{
|
|
287
|
+
"read_file",
|
|
288
|
+
"list_files",
|
|
289
|
+
"grep",
|
|
290
|
+
"create_file",
|
|
291
|
+
"replace_in_file",
|
|
292
|
+
"delete_file",
|
|
293
|
+
"delete_snippet",
|
|
294
|
+
"edit_file",
|
|
295
|
+
"agent_run_shell_command",
|
|
296
|
+
"ask_user_question",
|
|
297
|
+
"activate_skill",
|
|
298
|
+
"list_or_search_skills",
|
|
299
|
+
"agent_share_your_reasoning",
|
|
300
|
+
"universal_constructor",
|
|
301
|
+
"load_image_for_analysis",
|
|
302
|
+
}
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
def _stringify_result(result: Any) -> str:
|
|
307
|
+
"""Convert a tool result to a human-readable multi-line string.
|
|
308
|
+
|
|
309
|
+
Handles structured types (Pydantic BaseModel, dataclass, dict, list)
|
|
310
|
+
that produce single-line repr strings with escaped newlines when
|
|
311
|
+
passed through ``str()``.
|
|
312
|
+
"""
|
|
313
|
+
if isinstance(result, str):
|
|
314
|
+
return result
|
|
315
|
+
|
|
316
|
+
# Pydantic BaseModel -> JSON-like dict
|
|
317
|
+
if hasattr(result, "model_dump"):
|
|
318
|
+
try:
|
|
319
|
+
import json
|
|
320
|
+
|
|
321
|
+
return json.dumps(result.model_dump(), indent=2, default=str)
|
|
322
|
+
except Exception:
|
|
323
|
+
pass
|
|
324
|
+
|
|
325
|
+
# dataclass -> JSON-like dict
|
|
326
|
+
import dataclasses
|
|
327
|
+
|
|
328
|
+
if dataclasses.is_dataclass(result) and not isinstance(result, type):
|
|
329
|
+
try:
|
|
330
|
+
import json
|
|
331
|
+
|
|
332
|
+
return json.dumps(dataclasses.asdict(result), indent=2, default=str)
|
|
333
|
+
except Exception:
|
|
334
|
+
pass
|
|
335
|
+
|
|
336
|
+
# dict / list -> JSON
|
|
337
|
+
if isinstance(result, (dict, list)):
|
|
338
|
+
try:
|
|
339
|
+
import json
|
|
340
|
+
|
|
341
|
+
return json.dumps(result, indent=2, default=str)
|
|
342
|
+
except Exception:
|
|
343
|
+
pass
|
|
344
|
+
|
|
345
|
+
# Last resort: str() with escaped-newline recovery.
|
|
346
|
+
text = str(result)
|
|
347
|
+
if "\\n" in text and "\n" not in text:
|
|
348
|
+
text = text.replace("\\n", "\n")
|
|
349
|
+
return text
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
def _render_high_mode_tool_result(
|
|
353
|
+
tool_name: str,
|
|
354
|
+
tool_args: Any,
|
|
355
|
+
result: Any,
|
|
356
|
+
duration_ms: float,
|
|
357
|
+
) -> None:
|
|
358
|
+
"""Print a tool-result summary when ``output_level`` is ``high``.
|
|
359
|
+
|
|
360
|
+
Shows the return value that gets sent back to the model, truncated to
|
|
361
|
+
keep the terminal readable. Medium mode is unaffected.
|
|
362
|
+
"""
|
|
363
|
+
try:
|
|
364
|
+
from code_puppy.config import get_output_level
|
|
365
|
+
|
|
366
|
+
if get_output_level() != "high":
|
|
367
|
+
return
|
|
368
|
+
|
|
369
|
+
from rich.markup import escape as _esc
|
|
370
|
+
|
|
371
|
+
from code_puppy.agents.event_stream_handler import get_streaming_console
|
|
372
|
+
|
|
373
|
+
console = get_streaming_console()
|
|
374
|
+
dur_str = f"{duration_ms:.0f}" if duration_ms >= 1 else f"{duration_ms:.1f}"
|
|
375
|
+
|
|
376
|
+
# Sub-agent results: the response body was already streamed or
|
|
377
|
+
# rendered by display_non_streamed_result. Dumping the raw repr
|
|
378
|
+
# of AgentInvokeOutput would produce a single unreadable line
|
|
379
|
+
# with escaped newlines. Show a compact summary instead.
|
|
380
|
+
if tool_name in _ALREADY_RENDERED_TOOLS:
|
|
381
|
+
_render_high_mode_agent_result(console, tool_name, result, dur_str)
|
|
382
|
+
return
|
|
383
|
+
|
|
384
|
+
# Tools whose output was already rendered by the rich_renderer:
|
|
385
|
+
# show a compact duration-only line to avoid double-rendering.
|
|
386
|
+
if tool_name in _TOOLS_WITH_RENDERER:
|
|
387
|
+
console.print(
|
|
388
|
+
f"[dim] \u21a9 {_esc(tool_name)} returned ({dur_str} ms)[/dim]"
|
|
389
|
+
)
|
|
390
|
+
return
|
|
391
|
+
|
|
392
|
+
# General path: convert structured results to readable multi-line
|
|
393
|
+
# text (handles Pydantic models, dataclasses, dicts, lists).
|
|
394
|
+
# High mode shows the FULL result — no truncation. The user
|
|
395
|
+
# explicitly opted into maximum verbosity.
|
|
396
|
+
result_str = _stringify_result(result)
|
|
397
|
+
lines = result_str.splitlines()
|
|
398
|
+
total_lines = len(lines)
|
|
399
|
+
total_chars = len(result_str)
|
|
400
|
+
|
|
401
|
+
console.print(f"[dim] \u21a9 {_esc(tool_name)} returned ({dur_str} ms):[/dim]")
|
|
402
|
+
for line in lines:
|
|
403
|
+
console.print(f"[dim] {_esc(line)}[/dim]")
|
|
404
|
+
if total_lines > _HIGH_MODE_RESULT_FOOTER_THRESHOLD:
|
|
405
|
+
console.print(
|
|
406
|
+
f"[dim] ({total_lines} lines, ~{total_chars:,} chars)[/dim]"
|
|
407
|
+
)
|
|
408
|
+
except Exception:
|
|
409
|
+
pass # never crash for cosmetic output
|
|
410
|
+
|
|
411
|
+
|
|
412
|
+
def _render_high_mode_agent_result(
|
|
413
|
+
console: Any,
|
|
414
|
+
tool_name: str,
|
|
415
|
+
result: Any,
|
|
416
|
+
dur_str: str,
|
|
417
|
+
) -> None:
|
|
418
|
+
"""Compact one-liner for invoke_agent / invoke_agent_with_model results."""
|
|
419
|
+
from rich.markup import escape as _esc
|
|
420
|
+
|
|
421
|
+
agent_name = getattr(result, "agent_name", None) or "?"
|
|
422
|
+
error = getattr(result, "error", None)
|
|
423
|
+
response = getattr(result, "response", None)
|
|
424
|
+
|
|
425
|
+
if error:
|
|
426
|
+
console.print(
|
|
427
|
+
f"[dim] \u21a9 {_esc(tool_name)} returned ({dur_str} ms): "
|
|
428
|
+
f"[red]FAIL[/red] {_esc(agent_name)}[/dim]"
|
|
429
|
+
)
|
|
430
|
+
elif response is not None:
|
|
431
|
+
char_count = len(response)
|
|
432
|
+
console.print(
|
|
433
|
+
f"[dim] \u21a9 {_esc(tool_name)} returned ({dur_str} ms): "
|
|
434
|
+
f"[green]OK[/green] {_esc(agent_name)} ({char_count:,} chars)[/dim]"
|
|
435
|
+
)
|
|
436
|
+
else:
|
|
437
|
+
console.print(
|
|
438
|
+
f"[dim] \u21a9 {_esc(tool_name)} returned ({dur_str} ms): "
|
|
439
|
+
f"{_esc(agent_name)} (no response)[/dim]"
|
|
440
|
+
)
|
|
441
|
+
|
|
442
|
+
|
|
443
|
+
def _render_high_mode_stats() -> None:
|
|
444
|
+
"""Print a per-turn stats line when ``output_level`` is ``high``.
|
|
445
|
+
|
|
446
|
+
Reads the just-snapshotted cycle data from :class:`AgentRunStats` and
|
|
447
|
+
renders a compact dim line below the response showing model name,
|
|
448
|
+
TTFT, generation latency, and token counts.
|
|
449
|
+
"""
|
|
450
|
+
try:
|
|
451
|
+
from code_puppy.config import get_output_level
|
|
452
|
+
|
|
453
|
+
if get_output_level() != "high":
|
|
454
|
+
return
|
|
455
|
+
|
|
456
|
+
stats = AgentRunStats.get_last_cycle_stats()
|
|
457
|
+
# Only render if we actually have timing data.
|
|
458
|
+
if stats["ttft_seconds"] <= 0 and stats["gen_seconds"] <= 0:
|
|
459
|
+
return
|
|
460
|
+
|
|
461
|
+
from code_puppy.agents.event_stream_handler import get_streaming_console
|
|
462
|
+
|
|
463
|
+
console = get_streaming_console()
|
|
464
|
+
|
|
465
|
+
parts: list[str] = []
|
|
466
|
+
|
|
467
|
+
if stats["ttft_seconds"] > 0:
|
|
468
|
+
parts.append(f"TTFT {stats['ttft_seconds']:.2f} s")
|
|
469
|
+
|
|
470
|
+
if stats["gen_seconds"] > 0:
|
|
471
|
+
parts.append(f"gen {stats['gen_seconds']:.1f} s")
|
|
472
|
+
|
|
473
|
+
if stats["gen_tps"] > 0:
|
|
474
|
+
parts.append(f"{stats['gen_tps']:,.1f} t/s")
|
|
475
|
+
|
|
476
|
+
if stats["output_tokens"] > 0:
|
|
477
|
+
parts.append(f"~{stats['output_tokens']:,} output tokens (est)")
|
|
478
|
+
|
|
479
|
+
if parts:
|
|
480
|
+
line = " | ".join(parts)
|
|
481
|
+
console.print(f"\n[dim] {line}[/dim]")
|
|
482
|
+
except Exception:
|
|
483
|
+
# Never crash the app for cosmetic stats rendering.
|
|
484
|
+
pass
|
|
485
|
+
|
|
486
|
+
|
|
232
487
|
# ---------------------------------------------------------------------------
|
|
233
488
|
# Callback handlers
|
|
234
489
|
# ---------------------------------------------------------------------------
|
|
@@ -255,7 +510,7 @@ async def _on_agent_run_start(
|
|
|
255
510
|
"""Mark T0 = true request-start, before any HTTP packets fly."""
|
|
256
511
|
if is_subagent():
|
|
257
512
|
return
|
|
258
|
-
AgentRunStats.mark_request_start()
|
|
513
|
+
AgentRunStats.mark_request_start(model_name=model_name)
|
|
259
514
|
|
|
260
515
|
|
|
261
516
|
async def _on_stream_event(
|
|
@@ -287,6 +542,17 @@ async def _on_stream_event(
|
|
|
287
542
|
_record_text_tokens(args)
|
|
288
543
|
|
|
289
544
|
|
|
545
|
+
async def _on_post_tool_call(
|
|
546
|
+
tool_name: str,
|
|
547
|
+
tool_args: Any,
|
|
548
|
+
result: Any,
|
|
549
|
+
duration_ms: float,
|
|
550
|
+
context: Any = None,
|
|
551
|
+
) -> None:
|
|
552
|
+
"""Render the tool return value inline in ``high`` output mode."""
|
|
553
|
+
_render_high_mode_tool_result(tool_name, tool_args, result, duration_ms)
|
|
554
|
+
|
|
555
|
+
|
|
290
556
|
async def _on_agent_run_end(
|
|
291
557
|
agent_name: str,
|
|
292
558
|
model_name: str,
|
|
@@ -300,10 +566,14 @@ async def _on_agent_run_end(
|
|
|
300
566
|
|
|
301
567
|
Always fires regardless of success/failure so partial-but-real stats
|
|
302
568
|
still count toward the running averages.
|
|
569
|
+
|
|
570
|
+
In ``high`` output mode, a per-turn stats line is printed to the
|
|
571
|
+
streaming console so the user sees timing + token data inline.
|
|
303
572
|
"""
|
|
304
573
|
if is_subagent():
|
|
305
574
|
return
|
|
306
575
|
AgentRunStats.snapshot_cycle_into_aggregates()
|
|
576
|
+
_render_high_mode_stats()
|
|
307
577
|
|
|
308
578
|
|
|
309
579
|
# ---------------------------------------------------------------------------
|
|
@@ -313,7 +583,7 @@ _HOOKS_REGISTERED = False
|
|
|
313
583
|
|
|
314
584
|
|
|
315
585
|
def register_hooks() -> None:
|
|
316
|
-
"""Idempotently register the
|
|
586
|
+
"""Idempotently register the run-stats callback hooks."""
|
|
317
587
|
global _HOOKS_REGISTERED
|
|
318
588
|
if _HOOKS_REGISTERED:
|
|
319
589
|
return
|
|
@@ -323,6 +593,7 @@ def register_hooks() -> None:
|
|
|
323
593
|
register_callback("agent_run_start", _on_agent_run_start)
|
|
324
594
|
register_callback("stream_event", _on_stream_event)
|
|
325
595
|
register_callback("agent_run_end", _on_agent_run_end)
|
|
596
|
+
register_callback("post_tool_call", _on_post_tool_call)
|
|
326
597
|
_HOOKS_REGISTERED = True
|
|
327
598
|
except Exception:
|
|
328
599
|
# Callback module unavailable (extremely unlikely); silently skip
|
|
@@ -341,4 +612,5 @@ __all__ = [
|
|
|
341
612
|
"_on_agent_run_start",
|
|
342
613
|
"_on_stream_event",
|
|
343
614
|
"_on_agent_run_end",
|
|
615
|
+
"_on_post_tool_call",
|
|
344
616
|
]
|
|
@@ -46,6 +46,7 @@ from code_puppy.config import (
|
|
|
46
46
|
get_openai_reasoning_effort,
|
|
47
47
|
get_openai_reasoning_summary,
|
|
48
48
|
get_openai_verbosity,
|
|
49
|
+
get_output_level,
|
|
49
50
|
get_owner_name,
|
|
50
51
|
get_pack_agents_enabled,
|
|
51
52
|
get_protected_token_count,
|
|
@@ -489,6 +490,19 @@ _SAFETY = SettingsCategory(
|
|
|
489
490
|
_OUTPUT = SettingsCategory(
|
|
490
491
|
name="Output",
|
|
491
492
|
settings=(
|
|
493
|
+
Setting(
|
|
494
|
+
key="output_level",
|
|
495
|
+
display_name="Output Level",
|
|
496
|
+
description=(
|
|
497
|
+
"Unified density control for conversation output. "
|
|
498
|
+
"low = one-line peeks for tool calls & thinking, "
|
|
499
|
+
"medium = current default, "
|
|
500
|
+
"high = full metadata with timing, tokens, and verbose output."
|
|
501
|
+
),
|
|
502
|
+
type_hint="choice",
|
|
503
|
+
valid_values=("low", "medium", "high"),
|
|
504
|
+
effective_getter=get_output_level,
|
|
505
|
+
),
|
|
492
506
|
Setting(
|
|
493
507
|
key="smooth_response_stream",
|
|
494
508
|
display_name="Smooth Response Stream",
|
|
@@ -2015,6 +2015,51 @@ def set_suppress_informational_messages(enabled: bool):
|
|
|
2015
2015
|
set_config_value("suppress_informational_messages", "true" if enabled else "false")
|
|
2016
2016
|
|
|
2017
2017
|
|
|
2018
|
+
# ---------------------------------------------------------------------------
|
|
2019
|
+
# Output level (unified density control)
|
|
2020
|
+
# ---------------------------------------------------------------------------
|
|
2021
|
+
|
|
2022
|
+
_VALID_OUTPUT_LEVELS = frozenset({"low", "medium", "high"})
|
|
2023
|
+
|
|
2024
|
+
|
|
2025
|
+
def get_output_level() -> str:
|
|
2026
|
+
"""Return the current output density level.
|
|
2027
|
+
|
|
2028
|
+
Valid values: ``low``, ``medium``, ``high``. Default is ``medium``
|
|
2029
|
+
(current behaviour). The value is read from ``puppy.cfg`` with the
|
|
2030
|
+
key ``output_level``.
|
|
2031
|
+
|
|
2032
|
+
* **low** — collapse tool calls, thinking blocks, and info messages
|
|
2033
|
+
to one-line peeks. Great for focused work.
|
|
2034
|
+
* **medium** — current default behaviour.
|
|
2035
|
+
* **high** — full metadata: timing, tokens, verbose grep, all
|
|
2036
|
+
sub-agent output.
|
|
2037
|
+
"""
|
|
2038
|
+
cfg_val = get_value("output_level")
|
|
2039
|
+
if cfg_val is not None:
|
|
2040
|
+
normalised = str(cfg_val).strip().lower()
|
|
2041
|
+
if normalised in _VALID_OUTPUT_LEVELS:
|
|
2042
|
+
return normalised
|
|
2043
|
+
return "medium"
|
|
2044
|
+
|
|
2045
|
+
|
|
2046
|
+
def set_output_level(level: str) -> None:
|
|
2047
|
+
"""Set the output density level.
|
|
2048
|
+
|
|
2049
|
+
Args:
|
|
2050
|
+
level: One of ``low``, ``medium``, or ``high``.
|
|
2051
|
+
|
|
2052
|
+
Raises:
|
|
2053
|
+
ValueError: If *level* is not a valid choice.
|
|
2054
|
+
"""
|
|
2055
|
+
normalised = level.strip().lower()
|
|
2056
|
+
if normalised not in _VALID_OUTPUT_LEVELS:
|
|
2057
|
+
raise ValueError(
|
|
2058
|
+
f"Invalid output_level {level!r}; choose from low, medium, high"
|
|
2059
|
+
)
|
|
2060
|
+
set_config_value("output_level", normalised)
|
|
2061
|
+
|
|
2062
|
+
|
|
2018
2063
|
# API Key management functions
|
|
2019
2064
|
def get_api_key(key_name: str) -> str:
|
|
2020
2065
|
"""Get an API key from puppy.cfg.
|