code-puppy-core-plugins 0.0.45__tar.gz → 0.0.47__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_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/PKG-INFO +2 -2
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/claude_code_oauth/model_provider.py +5 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/herdr/README.md +58 -7
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/herdr/client.py +188 -9
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/herdr/register_callbacks.py +12 -4
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/herdr/reporter.py +129 -4
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/herdr/smoke.py +68 -10
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/herdr/sources.py +87 -7
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/pyproject.toml +2 -2
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/.gitignore +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/LICENSE +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/README.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/acp/README.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/acp/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/acp/agent.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/acp/bridge.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/acp/capabilities.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/acp/commands.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/acp/content.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/acp/io_delegation.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/acp/mcp_config.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/acp/permissions.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/acp/persistence.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/acp/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/acp/replay.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/acp/session.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/acp/session_config.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/acp/state.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/agent_creator_skill/SKILL.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/agent_creator_skill/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/agent_creator_skill/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/agent_skills/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/agent_skills/config.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/agent_skills/discovery.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/agent_skills/downloader.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/agent_skills/enabled_skills.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/agent_skills/installer.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/agent_skills/metadata.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/agent_skills/prompt_builder.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/agent_skills/provider.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/agent_skills/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/agent_skills/remote_catalog.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/agent_skills/skill_catalog.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/agent_skills/skill_commands.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/agent_skills/skills_install_menu.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/agent_skills/skills_menu.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/auto_continue/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/auto_continue/classifier.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/auto_continue/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/aws_bedrock/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/aws_bedrock/config.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/aws_bedrock/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/aws_bedrock/utils.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/azure_foundry/README.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/azure_foundry/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/azure_foundry/config.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/azure_foundry/discovery.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/azure_foundry/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/azure_foundry/token.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/azure_foundry/utils.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/btw/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/btw/inline_view.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/btw/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/btw/side_query.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/chatgpt_oauth/IMAGEGEN_SKILL.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/chatgpt_oauth/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/chatgpt_oauth/config.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/chatgpt_oauth/image_generation.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/chatgpt_oauth/image_tool.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/chatgpt_oauth/model_catalog.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/chatgpt_oauth/oauth_flow.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/chatgpt_oauth/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/chatgpt_oauth/test_plugin.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/chatgpt_oauth/usage.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/chatgpt_oauth/utils.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/claude_code_hooks/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/claude_code_hooks/config.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/claude_code_hooks/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/claude_code_hooks/trust.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/claude_code_oauth/README.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/claude_code_oauth/SETUP.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/claude_code_oauth/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/claude_code_oauth/config.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/claude_code_oauth/fast_mode.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/claude_code_oauth/model_filter.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/claude_code_oauth/prompt_handler.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/claude_code_oauth/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/claude_code_oauth/runtime_credentials.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/claude_code_oauth/test_plugin.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/claude_code_oauth/token_refresh_heartbeat.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/claude_code_oauth/token_store.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/claude_code_oauth/utils.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/code_puppy_agent/AGENTS_AND_TOOLS.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/code_puppy_agent/MODELS_AND_MCP.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/code_puppy_agent/PLUGINS_AND_CALLBACKS.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/code_puppy_agent/SESSIONS_AND_HISTORY.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/code_puppy_agent/SKILL.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/code_puppy_agent/SKILLS_SYSTEM.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/code_puppy_agent/SYSTEM_PROMPT_CONFIG_AND_I18N.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/code_puppy_agent/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/code_puppy_agent/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/completion_notification/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/completion_notification/config.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/completion_notification/locales/en-US.json +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/completion_notification/locales/es.json +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/completion_notification/locales/fr-CA.json +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/completion_notification/notifier.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/completion_notification/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/computer_use/NativeCapture.swift +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/computer_use/README.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/computer_use/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/computer_use/accessibility.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/computer_use/activation.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/computer_use/backend.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/computer_use/backend_types.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/computer_use/capture.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/computer_use/commands.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/computer_use/geometry.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/computer_use/inline_image.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/computer_use/keycodes.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/computer_use/policy.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/computer_use/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/computer_use/safety.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/computer_use/settle.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/computer_use/state.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/computer_use/tools.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/context_indicator/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/context_indicator/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/context_indicator/usage.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/copilot_auth/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/copilot_auth/config.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/copilot_auth/reasoning_client.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/copilot_auth/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/copilot_auth/utils.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/customizable_commands/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/customizable_commands/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/dbos_durable_exec/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/dbos_durable_exec/cancel.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/dbos_durable_exec/commands.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/dbos_durable_exec/config.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/dbos_durable_exec/lifecycle.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/dbos_durable_exec/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/dbos_durable_exec/runtime.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/dbos_durable_exec/startup_lock.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/dbos_durable_exec/workflow_ids.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/dbos_durable_exec/wrapper.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/destructive_command_guard/AGENTS.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/destructive_command_guard/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/destructive_command_guard/detector.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/destructive_command_guard/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/emoji_filter/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/emoji_filter/config.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/emoji_filter/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/emoji_filter/stripper.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/empty_html_comment_filter/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/example_custom_command/README.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/example_custom_command/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/file_permission_handler/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/file_permission_handler/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/flux_bootstrap/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/_docs/README.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/_docs/cheatsheet.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/_docs/pipeline.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/_docs/synopsis.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/about.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/address-feedback.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/ask.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/aug.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/auto-pilot.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/cheatsheet.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/commit.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/config.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/create-pr.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/exec.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/new.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/qa.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/rebase.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/review.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/split.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/squash-commits.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/status.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/tests.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/flux_bootstrap/bundled/scripts/flux_about.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/flux_bootstrap/bundled/scripts/flux_cheatsheet.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/flux_bootstrap/bundled/scripts/flux_status.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/flux_bootstrap/installer.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/flux_bootstrap/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/force_push_guard/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/force_push_guard/detector.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/force_push_guard/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/fork/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/fork/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/frontend_emitter/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/frontend_emitter/emitter.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/frontend_emitter/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/frontend_emitter/session_context.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/grok_oauth/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/grok_oauth/config.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/grok_oauth/oauth_flow.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/grok_oauth/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/grok_oauth/utils.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/herdr/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/hook_creator/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/hook_creator/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/hook_manager/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/hook_manager/config.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/hook_manager/hooks_menu.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/hook_manager/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/hook_manager/trust_handler.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/logfire_oauth/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/logfire_oauth/oauth.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/logfire_oauth/query_tool.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/logfire_oauth/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/logfire_sessions/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/logfire_sessions/mirror.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/logfire_sessions/query.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/logfire_sessions/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/logfire_sessions/sync.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/meta_oauth/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/meta_oauth/config.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/meta_oauth/oauth_flow.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/meta_oauth/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/meta_oauth/utils.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/namespace_skill_search/README.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/namespace_skill_search/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/namespace_skill_search/namespaces.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/namespace_skill_search/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/namespace_skill_search/search_tool.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/no_tools/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/no_tools/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/oauth_pasteback.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/oauth_puppy_html.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/obsidian_agent/README.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/obsidian_agent/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/obsidian_agent/agent_obsidian.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/obsidian_agent/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/ollama/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/ollama/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/ollama_setup/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/ollama_setup/completer.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/ollama_setup/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/openrouter_oauth/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/openrouter_oauth/config.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/openrouter_oauth/oauth_flow.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/openrouter_oauth/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/openrouter_oauth/test_plugin.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/plugin_list/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/plugin_list/plugin_contributions.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/plugin_list/plugin_meta.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/plugin_list/plugin_text_utils.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/plugin_list/plugins_menu.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/plugin_list/plugins_menu_render.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/plugin_list/project_trust_flow.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/plugin_list/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/pop_command/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/pop_command/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/profiles/README.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/profiles/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/profiles/config.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/profiles/locales/en-US.json +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/profiles/menu.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/profiles/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/prompt_newline/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/prompt_newline/config.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/prompt_newline/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/prune/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/prune/prune_menu.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/prune/prune_model.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/prune/prune_render.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/prune/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/puppy_kennel/README.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/puppy_kennel/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/puppy_kennel/commands.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/puppy_kennel/config.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/puppy_kennel/kennel.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/puppy_kennel/packer.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/puppy_kennel/recorder.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/puppy_kennel/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/puppy_kennel/retriever.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/puppy_kennel/schema.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/puppy_kennel/state.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/puppy_kennel/tools.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/puppy_kennel/wings.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/puppy_spinner/README.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/puppy_spinner/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/puppy_spinner/builtin_frames.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/puppy_spinner/commands.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/puppy_spinner/picker.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/puppy_spinner/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/puppy_spinner/spinners.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/qa_kitten_skill/SKILL.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/qa_kitten_skill/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/qa_kitten_skill/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/quick_resume/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/quick_resume/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/review_pr/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/review_pr/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/session_namer/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/session_namer/namer.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/session_namer/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/spill/LICENSE.deepseek +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/spill/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/spill/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/spill/store.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/stack_dump/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/stack_dump/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/statusline/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/statusline/config.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/statusline/payload.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/statusline/prompt_patch.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/statusline/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/statusline/runner.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/statusline/statusline_command.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/steer_queue/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/steer_queue/queue_menu.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/steer_queue/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/subagent_panel/README.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/subagent_panel/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/subagent_panel/coalesce_patch.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/subagent_panel/panel_render.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/subagent_panel/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/subagent_panel/resume_repaint.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/subagent_panel/state.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/switch_agent_resume/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/switch_agent_resume/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/termflow_tui.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/theme/README.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/theme/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/theme/bundled_palettes.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/theme/content_styles.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/theme/osc_palette.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/theme/picker.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/theme/prompt_toolkit_theme.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/theme/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/theme/rich_themes.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/theme/themes.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/timestamp_heartbeat/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/timestamp_heartbeat/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/token_ratio_learner/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/token_ratio_learner/ratios.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/token_ratio_learner/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/universal_constructor/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/universal_constructor/models.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/universal_constructor/provider.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/universal_constructor/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/universal_constructor/registry.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/universal_constructor/sandbox.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/web_retriever_skill/SKILL.md +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/web_retriever_skill/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/web_retriever_skill/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/wiggum/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/wiggum/goal_runs.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/wiggum/judge.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/wiggum/judge_config.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/wiggum/judges_menu.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/wiggum/register_callbacks.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/wiggum/state.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/yolo_cli/__init__.py +0 -0
- {code_puppy_core_plugins-0.0.45 → code_puppy_core_plugins-0.0.47}/code_puppy_core_plugins/yolo_cli/register_callbacks.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: code-puppy-core-plugins
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.47
|
|
4
4
|
Summary: Official plugin bundle for Code Puppy
|
|
5
5
|
Project-URL: Repository, https://github.com/mpfaffenberger/code_puppy_core_plugins
|
|
6
6
|
Project-URL: Homepage, https://github.com/mpfaffenberger/code_puppy_core_plugins
|
|
@@ -15,7 +15,7 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.13
|
|
16
16
|
Requires-Python: <3.15,>=3.11
|
|
17
17
|
Requires-Dist: httpx<1,>=0.24.1
|
|
18
|
-
Requires-Dist: pydantic-ai-slim[anthropic,mcp,openai]<3,>=2.
|
|
18
|
+
Requires-Dist: pydantic-ai-slim[anthropic,mcp,openai]<3,>=2.35.0
|
|
19
19
|
Description-Content-Type: text/markdown
|
|
20
20
|
|
|
21
21
|
# Code Puppy Core Plugins
|
|
@@ -123,10 +123,15 @@ def create_claude_code_model(model_name: str, model_config: Dict, config: Dict)
|
|
|
123
123
|
),
|
|
124
124
|
)
|
|
125
125
|
|
|
126
|
+
# The transport already retries 429/5xx/connection errors with backoff,
|
|
127
|
+
# and the agent runtime retries the turn on top of that. The SDK's own
|
|
128
|
+
# retries would multiply every hard failure 3x -- a 429 storm is exactly
|
|
129
|
+
# when hammering the endpoint makes things worse.
|
|
126
130
|
anthropic_client = AsyncAnthropic(
|
|
127
131
|
base_url=url,
|
|
128
132
|
http_client=client,
|
|
129
133
|
auth_token=api_key,
|
|
134
|
+
max_retries=0,
|
|
130
135
|
)
|
|
131
136
|
|
|
132
137
|
def _update_runtime_token(access_token: str) -> None:
|
|
@@ -11,13 +11,14 @@ This plugin teaches code-puppy to report that state authoritatively.
|
|
|
11
11
|
|
|
12
12
|
## What it does
|
|
13
13
|
|
|
14
|
-
herdr injects
|
|
14
|
+
herdr injects four environment variables into every pane it owns:
|
|
15
15
|
|
|
16
16
|
| variable | meaning |
|
|
17
17
|
| ------------------- | ----------------------------------------- |
|
|
18
18
|
| `HERDR_ENV=1` | this shell is running inside a herdr pane |
|
|
19
19
|
| `HERDR_SOCKET_PATH` | herdr's local control socket |
|
|
20
20
|
| `HERDR_PANE_ID` | the pane this process owns (e.g. `w1:p1`) |
|
|
21
|
+
| `HERDR_TAB_ID` | the workspace tab (e.g. `w1:t1`) |
|
|
21
22
|
|
|
22
23
|
On startup the plugin checks for those. If they're absent it does
|
|
23
24
|
**nothing** -- zero overhead, zero output, no behaviour change, no socket,
|
|
@@ -94,6 +95,55 @@ when the reference actually changes (after `/clear`, `/session new`,
|
|
|
94
95
|
This is a stable *reference*; automatic process restoration from it is
|
|
95
96
|
**unverified** and not claimed here.
|
|
96
97
|
|
|
98
|
+
## Conversation titles
|
|
99
|
+
|
|
100
|
+
The `session_namer` plugin auto-names every conversation (the titles you
|
|
101
|
+
see in `/resume`). This plugin propagates the current session's title to
|
|
102
|
+
two herdr surfaces:
|
|
103
|
+
|
|
104
|
+
* the pane's **presentation title**, which herdr renders as the pane
|
|
105
|
+
border label and the sidebar `pane` token, and
|
|
106
|
+
* the **workspace tab label** in herdr's tab bar -- but only while the
|
|
107
|
+
tab holds a single pane (the one running this code-puppy). The tab bar
|
|
108
|
+
is a user-managed surface, so a tab shared with other panes is never
|
|
109
|
+
touched.
|
|
110
|
+
|
|
111
|
+
Add the `pane` token to `rows_by_agent` to show the title in the sidebar
|
|
112
|
+
too:
|
|
113
|
+
|
|
114
|
+
```toml
|
|
115
|
+
[ui.sidebar.agents.rows_by_agent]
|
|
116
|
+
codepuppy = [
|
|
117
|
+
["state_icon", "workspace", "tab"],
|
|
118
|
+
["agent", "$model", "pane"],
|
|
119
|
+
["$context", "$tokens"],
|
|
120
|
+
]
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
The title is read from the session metadata sidecar that `session_namer`
|
|
124
|
+
maintains (the same store `/resume` reads). The pane presentation title
|
|
125
|
+
rides the same `pane.report_metadata` envelope as the token payload:
|
|
126
|
+
herdr replaces the whole per-source metadata entry on each report, so
|
|
127
|
+
every turn-end report re-sends the title (or a `clear_title` on a
|
|
128
|
+
set-to-none transition) and a title change is reported title-only the
|
|
129
|
+
moment it is seen. The tab label follows the same title changes via
|
|
130
|
+
`tab.rename`, guarded by a `tab.get` read of the tab's `pane_count`; on
|
|
131
|
+
a clean exit the original label is restored -- but only while the tab
|
|
132
|
+
still shows the label we last set, so a tab you renamed by hand is never
|
|
133
|
+
clobbered (a crashed exit simply leaves the last title in place, like
|
|
134
|
+
the stale-pane case above).
|
|
135
|
+
|
|
136
|
+
Because the namer names the session *asynchronously* after each autosave,
|
|
137
|
+
a bounded background wait (2s ticks, 90s ceiling -- the namer's own model
|
|
138
|
+
call is capped at 60s) picks the title up a few seconds after the turn
|
|
139
|
+
ends instead of waiting for the next turn. The wait is single-flight,
|
|
140
|
+
pinned to the session that triggered it, and skipped when the
|
|
141
|
+
`session_namer` plugin is disabled via its `session_namer` config value.
|
|
142
|
+
A session switch clears the previous session's title on the next prompt
|
|
143
|
+
(and restores the tab label). As with the token payload, the pane title
|
|
144
|
+
self-expires after the 24h metadata TTL, and all of this is decorative:
|
|
145
|
+
it never touches the authoritative state and is a no-op outside herdr.
|
|
146
|
+
|
|
97
147
|
## Notifications are herdr's job
|
|
98
148
|
|
|
99
149
|
The plugin sends no notifications itself. herdr derives attention and
|
|
@@ -103,7 +153,8 @@ plugin's only job is to report accurate state.
|
|
|
103
153
|
|
|
104
154
|
## Release on exit
|
|
105
155
|
|
|
106
|
-
On `session_end` / `shutdown` the plugin
|
|
156
|
+
On `session_end` / `shutdown` the plugin restores the workspace tab label
|
|
157
|
+
(if it relabelled one) and then calls `pane.release_agent` once
|
|
107
158
|
(idempotent, bounded) so herdr knows code-puppy has let go of the pane --
|
|
108
159
|
no lingering stale `working`. There is no intermediate `idle` report on
|
|
109
160
|
shutdown; if herdr is unavailable the release is bounded and can never
|
|
@@ -147,9 +198,9 @@ state, metadata, and activity.
|
|
|
147
198
|
| ----------------------- | ------------------------------------------- |
|
|
148
199
|
| `client.py` | herdr socket transport (JSON, worker thread)|
|
|
149
200
|
| `reporter.py` | event -> state machine (refcount + dedup) |
|
|
150
|
-
| `sources.py` | fail-soft adapters (tokens / session / msg) |
|
|
201
|
+
| `sources.py` | fail-soft adapters (tokens / title / session / msg) |
|
|
151
202
|
| `register_callbacks.py` | callback wiring + env activation guard |
|
|
152
|
-
| `smoke.py` | manual live smoke test (disposable pane)
|
|
203
|
+
| `smoke.py` | manual live smoke test (disposable pane + tab) |
|
|
153
204
|
|
|
154
205
|
## Live smoke test
|
|
155
206
|
|
|
@@ -163,6 +214,6 @@ python -m code_puppy_core_plugins.herdr.smoke
|
|
|
163
214
|
|
|
164
215
|
It creates its **own** disposable pane, drives the real client through
|
|
165
216
|
every protocol-16 method (state edges, session reference, metadata,
|
|
166
|
-
release), reads each result back with
|
|
167
|
-
disposable pane -- your working pane is
|
|
168
|
-
any check fails.
|
|
217
|
+
conversation title, release), reads each result back with
|
|
218
|
+
`herdr pane get`, then closes the disposable pane -- your working pane is
|
|
219
|
+
never touched. Exits non-zero if any check fails.
|
|
@@ -7,13 +7,16 @@ environment variables:
|
|
|
7
7
|
* ``HERDR_ENV=1`` -- marks the pane as herdr-managed
|
|
8
8
|
* ``HERDR_SOCKET_PATH`` -- path to herdr's local control socket
|
|
9
9
|
* ``HERDR_PANE_ID`` -- the pane this process owns (e.g. ``w1:p1``)
|
|
10
|
+
* ``HERDR_TAB_ID`` -- the workspace tab (e.g. ``w1:t1``); optional
|
|
10
11
|
|
|
11
12
|
This module speaks herdr's newline-delimited JSON socket protocol far
|
|
12
13
|
enough to call ``pane.report_agent`` / ``pane.report_agent_session`` /
|
|
13
|
-
``pane.report_metadata`` / ``pane.release_agent
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
``pane.report_metadata`` / ``pane.release_agent`` -- plus ``tab.get`` /
|
|
15
|
+
``tab.rename`` for the workspace-tab label (only while the tab holds a
|
|
16
|
+
single pane). It reads herdr's ack (and retries a few times if it
|
|
17
|
+
doesn't come) so an authoritative state edge is never silently lost, but
|
|
18
|
+
it never raises into the caller: reporting agent state must never be
|
|
19
|
+
able to disturb the agent itself.
|
|
17
20
|
|
|
18
21
|
Delivery runs on a single daemon worker thread fed by **coalescing
|
|
19
22
|
mailbox slots** rather than an unbounded queue:
|
|
@@ -75,6 +78,8 @@ _M_STATE = "pane.report_agent"
|
|
|
75
78
|
_M_SESSION = "pane.report_agent_session"
|
|
76
79
|
_M_METADATA = "pane.report_metadata"
|
|
77
80
|
_M_RELEASE = "pane.release_agent"
|
|
81
|
+
_M_TAB_GET = "tab.get"
|
|
82
|
+
_M_TAB_RENAME = "tab.rename"
|
|
78
83
|
|
|
79
84
|
|
|
80
85
|
class HerdrClient:
|
|
@@ -84,9 +89,11 @@ class HerdrClient:
|
|
|
84
89
|
self,
|
|
85
90
|
socket_path: Optional[str] = None,
|
|
86
91
|
pane_id: Optional[str] = None,
|
|
92
|
+
tab_id: Optional[str] = None,
|
|
87
93
|
) -> None:
|
|
88
94
|
self._socket_path = socket_path or os.environ.get("HERDR_SOCKET_PATH")
|
|
89
95
|
self._pane_id = pane_id or os.environ.get("HERDR_PANE_ID")
|
|
96
|
+
self._tab_id = tab_id or os.environ.get("HERDR_TAB_ID")
|
|
90
97
|
self._active = bool(
|
|
91
98
|
os.environ.get("HERDR_ENV") == "1"
|
|
92
99
|
and self._socket_path
|
|
@@ -102,6 +109,13 @@ class HerdrClient:
|
|
|
102
109
|
# Decorative lane (latest-wins, discarded on release).
|
|
103
110
|
self._message: Optional[Dict[str, Any]] = None
|
|
104
111
|
self._metadata: Optional[Dict[str, Any]] = None
|
|
112
|
+
# Tab-label job slot (latest-wins; survives release scheduling so
|
|
113
|
+
# the exit-time restore still drains before the release).
|
|
114
|
+
self._tab: Optional[Dict[str, Any]] = None
|
|
115
|
+
# Tab-label ownership state (guarded by ``self._cond``).
|
|
116
|
+
self._tab_original: Optional[str] = None
|
|
117
|
+
self._tab_renamed = False
|
|
118
|
+
self._tab_last_label: Optional[str] = None
|
|
105
119
|
# Terminal release slot.
|
|
106
120
|
self._release: Optional[Dict[str, Any]] = None
|
|
107
121
|
|
|
@@ -173,17 +187,74 @@ class HerdrClient:
|
|
|
173
187
|
return
|
|
174
188
|
self._put("_session", params)
|
|
175
189
|
|
|
176
|
-
def report_metadata(
|
|
177
|
-
|
|
178
|
-
|
|
190
|
+
def report_metadata(
|
|
191
|
+
self,
|
|
192
|
+
tokens: Optional[Dict[str, Any]] = None,
|
|
193
|
+
*,
|
|
194
|
+
title: Optional[str] = None,
|
|
195
|
+
clear_title: bool = False,
|
|
196
|
+
) -> None:
|
|
197
|
+
"""Report pane metadata on the decorative lane (latest wins).
|
|
198
|
+
|
|
199
|
+
``tokens`` are herdr's ``$token`` sidebar values; ``title`` sets the
|
|
200
|
+
pane presentation title (pane border + sidebar ``pane`` token);
|
|
201
|
+
``clear_title`` drops it. No-op when nothing is set: herdr rejects
|
|
202
|
+
empty metadata envelopes. Note herdr replaces the whole per-source
|
|
203
|
+
metadata entry on each report, so a caller that sets a title must
|
|
204
|
+
keep re-sending it on later tokens-only reports or it is wiped.
|
|
205
|
+
"""
|
|
206
|
+
if clear_title and title is not None:
|
|
207
|
+
# Caller bug: herdr rejects setting and clearing in one report.
|
|
208
|
+
# Clearing wins -- a stale title is less wrong than a rejected one.
|
|
209
|
+
title = None
|
|
210
|
+
if not clear_title and title is None and not tokens:
|
|
179
211
|
return
|
|
180
212
|
params: Dict[str, Any] = {
|
|
181
213
|
"applies_to_source": SOURCE,
|
|
182
214
|
"ttl_ms": _METADATA_TTL_MS,
|
|
183
|
-
"tokens": dict(tokens),
|
|
184
215
|
}
|
|
216
|
+
if clear_title:
|
|
217
|
+
params["clear_title"] = True
|
|
218
|
+
elif title is not None:
|
|
219
|
+
params["title"] = title
|
|
220
|
+
if tokens:
|
|
221
|
+
params["tokens"] = dict(tokens)
|
|
185
222
|
self._put("_metadata", params)
|
|
186
223
|
|
|
224
|
+
def set_tab_label(
|
|
225
|
+
self, label: Optional[str], *, expected: Optional[str] = None
|
|
226
|
+
) -> None:
|
|
227
|
+
"""Set the label of the herdr workspace tab we run in, or restore it.
|
|
228
|
+
|
|
229
|
+
``label=None`` restores the label that was in place when we first
|
|
230
|
+
took ownership (and only while the tab still shows ``expected`` --
|
|
231
|
+
a label the user changed meanwhile is left alone). The tab is only
|
|
232
|
+
ever relabelled when it holds a single pane: the tab bar is a
|
|
233
|
+
user-managed surface, and a tab shared with other panes is never
|
|
234
|
+
touched. Enqueued on the decorative lane; never blocks the caller,
|
|
235
|
+
and is a no-op when ``HERDR_TAB_ID`` is unset.
|
|
236
|
+
"""
|
|
237
|
+
if not self._active or not self._tab_id:
|
|
238
|
+
return
|
|
239
|
+
with self._cond:
|
|
240
|
+
if label is not None:
|
|
241
|
+
if label == self._tab_last_label:
|
|
242
|
+
return
|
|
243
|
+
if (
|
|
244
|
+
self._tab is not None
|
|
245
|
+
and self._tab["op"] == "set"
|
|
246
|
+
and self._tab["label"] == label
|
|
247
|
+
):
|
|
248
|
+
return # an identical set is already queued
|
|
249
|
+
elif not self._tab_renamed and self._tab is None:
|
|
250
|
+
return # never renamed and nothing queued: nothing to restore
|
|
251
|
+
self._tab = {
|
|
252
|
+
"op": "restore" if label is None else "set",
|
|
253
|
+
"label": label,
|
|
254
|
+
"expected": expected,
|
|
255
|
+
}
|
|
256
|
+
self._cond.notify()
|
|
257
|
+
|
|
187
258
|
def _put(self, slot: str, params: Dict[str, Any]) -> None:
|
|
188
259
|
if not self._active:
|
|
189
260
|
return
|
|
@@ -249,6 +320,11 @@ class HerdrClient:
|
|
|
249
320
|
if self._metadata is not None:
|
|
250
321
|
params, self._metadata = self._metadata, None
|
|
251
322
|
return _M_METADATA, params
|
|
323
|
+
# The tab job drains even while closing: the exit-time label
|
|
324
|
+
# restore is shutdown work and must land before the release.
|
|
325
|
+
if self._tab is not None:
|
|
326
|
+
job, self._tab = self._tab, None
|
|
327
|
+
return _M_TAB_RENAME, job
|
|
252
328
|
if self._closing and self._release is not None:
|
|
253
329
|
params, self._release = self._release, None
|
|
254
330
|
return _M_RELEASE, params
|
|
@@ -266,7 +342,10 @@ class HerdrClient:
|
|
|
266
342
|
self._cond.wait()
|
|
267
343
|
job = self._take_next_locked()
|
|
268
344
|
method, params = job
|
|
269
|
-
|
|
345
|
+
if method == _M_TAB_RENAME:
|
|
346
|
+
self._do_tab(params)
|
|
347
|
+
else:
|
|
348
|
+
self._send(method, params)
|
|
270
349
|
if method == _M_RELEASE:
|
|
271
350
|
self._released.set()
|
|
272
351
|
return
|
|
@@ -286,6 +365,10 @@ class HerdrClient:
|
|
|
286
365
|
**params,
|
|
287
366
|
},
|
|
288
367
|
}
|
|
368
|
+
self._transmit(method, envelope)
|
|
369
|
+
|
|
370
|
+
def _transmit(self, method: str, envelope: Dict[str, Any]) -> None:
|
|
371
|
+
"""Fire-and-forget send with retry-until-acked. Never raises."""
|
|
289
372
|
payload = (json.dumps(envelope) + "\n").encode("utf-8")
|
|
290
373
|
last_exc: Optional[Exception] = None
|
|
291
374
|
for attempt in range(_SEND_ATTEMPTS):
|
|
@@ -335,5 +418,101 @@ class HerdrClient:
|
|
|
335
418
|
pipe.write(payload)
|
|
336
419
|
return bool(pipe.readline(_ACK_BYTES))
|
|
337
420
|
|
|
421
|
+
# -- tab label -----------------------------------------------------
|
|
422
|
+
|
|
423
|
+
def _do_tab(self, job: Dict[str, Any]) -> None:
|
|
424
|
+
"""Apply a tab-label set or restore, with the ownership gate.
|
|
425
|
+
|
|
426
|
+
Runs on the worker. The tab is only ever relabelled by us while it
|
|
427
|
+
holds exactly one pane: herdr's tab bar is a user-managed surface,
|
|
428
|
+
and a tab shared with other panes is never touched. The original
|
|
429
|
+
label is captured on first takeover and restored on a clean exit
|
|
430
|
+
-- but only while the tab still shows the label we last set, so a
|
|
431
|
+
manual rename by the user is never clobbered.
|
|
432
|
+
"""
|
|
433
|
+
info = self._request(_M_TAB_GET, {"tab_id": self._tab_id}) or {}
|
|
434
|
+
result = info.get("result") if isinstance(info.get("result"), dict) else {}
|
|
435
|
+
tab = result.get("tab") if isinstance(result.get("tab"), dict) else {}
|
|
436
|
+
if tab.get("pane_count") != 1:
|
|
437
|
+
return # shared or vanished tab: leave its label alone
|
|
438
|
+
current = tab.get("label")
|
|
439
|
+
label = job.get("label")
|
|
440
|
+
with self._cond:
|
|
441
|
+
if label is None: # restore
|
|
442
|
+
if not (self._tab_renamed and self._tab_original):
|
|
443
|
+
return
|
|
444
|
+
expected = job.get("expected")
|
|
445
|
+
if expected is not None and current != expected:
|
|
446
|
+
return # the user changed it meanwhile; leave it
|
|
447
|
+
target = self._tab_original
|
|
448
|
+
else:
|
|
449
|
+
if not self._tab_renamed:
|
|
450
|
+
self._tab_original = current
|
|
451
|
+
self._tab_renamed = True
|
|
452
|
+
self._tab_last_label = label
|
|
453
|
+
target = label
|
|
454
|
+
if current != target:
|
|
455
|
+
seq = self._next_seq()
|
|
456
|
+
self._transmit(
|
|
457
|
+
_M_TAB_RENAME,
|
|
458
|
+
{
|
|
459
|
+
"id": f"{SOURCE}:{seq}",
|
|
460
|
+
"method": _M_TAB_RENAME,
|
|
461
|
+
"params": {"tab_id": self._tab_id, "label": target},
|
|
462
|
+
},
|
|
463
|
+
)
|
|
464
|
+
if label is None:
|
|
465
|
+
with self._cond:
|
|
466
|
+
self._tab_renamed = False
|
|
467
|
+
self._tab_original = None
|
|
468
|
+
self._tab_last_label = None
|
|
469
|
+
|
|
470
|
+
def _request(self, method: str, params: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
|
471
|
+
"""One request/response round-trip on a fresh connection.
|
|
472
|
+
|
|
473
|
+
Used only for the tab-info read (``tab.get``). Unlike fire-and-forget
|
|
474
|
+
reports, the response carries data we need; any failure degrades to
|
|
475
|
+
``None`` and the caller simply skips the operation.
|
|
476
|
+
"""
|
|
477
|
+
seq = self._next_seq()
|
|
478
|
+
envelope = {"id": f"{SOURCE}:{seq}", "method": method, "params": params}
|
|
479
|
+
payload = (json.dumps(envelope) + "\n").encode("utf-8")
|
|
480
|
+
try:
|
|
481
|
+
raw = (
|
|
482
|
+
self._request_pipe(payload)
|
|
483
|
+
if os.name == "nt"
|
|
484
|
+
else self._request_unix(payload)
|
|
485
|
+
)
|
|
486
|
+
except (OSError, ValueError):
|
|
487
|
+
logger.debug("herdr %s failed", method, exc_info=True)
|
|
488
|
+
return None
|
|
489
|
+
if not raw:
|
|
490
|
+
return None
|
|
491
|
+
try:
|
|
492
|
+
reply = json.loads(raw.decode("utf-8", "replace"))
|
|
493
|
+
except ValueError:
|
|
494
|
+
return None
|
|
495
|
+
return reply if isinstance(reply, dict) else None
|
|
496
|
+
|
|
497
|
+
def _request_unix(self, payload: bytes) -> bytes:
|
|
498
|
+
with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as sock:
|
|
499
|
+
sock.settimeout(_CONNECT_TIMEOUT_S)
|
|
500
|
+
sock.connect(self._socket_path) # type: ignore[arg-type]
|
|
501
|
+
sock.sendall(payload)
|
|
502
|
+
line = b""
|
|
503
|
+
while not line.endswith(b"\n") and len(line) < 65536:
|
|
504
|
+
chunk = sock.recv(_ACK_BYTES)
|
|
505
|
+
if not chunk:
|
|
506
|
+
break
|
|
507
|
+
line += chunk
|
|
508
|
+
return line
|
|
509
|
+
|
|
510
|
+
def _request_pipe(self, payload: bytes) -> bytes:
|
|
511
|
+
# Same named-pipe mapping as ``_deliver_pipe`` (see there).
|
|
512
|
+
pipe_name = "\\\\.\\pipe\\" + str(self._socket_path)
|
|
513
|
+
with open(pipe_name, "r+b", buffering=0) as pipe:
|
|
514
|
+
pipe.write(payload)
|
|
515
|
+
return pipe.readline(65536)
|
|
516
|
+
|
|
338
517
|
|
|
339
518
|
__all__ = ["HerdrClient", "SOURCE", "AGENT"]
|
|
@@ -31,13 +31,15 @@ Callback -> effect:
|
|
|
31
31
|
* ``agent_run_cancel`` / ``interactive_turn_end`` .... reset -> idle
|
|
32
32
|
* ``interactive_turn_cancel`` ........................ reset -> idle
|
|
33
33
|
* ``awaiting_user_input`` ............................ blocked <-> not
|
|
34
|
+
* ``post_autosave`` .................................. title refresh / wait
|
|
34
35
|
|
|
35
36
|
Session identity is the durable autosave (name, path) resolved by
|
|
36
37
|
``sources.current_session_ref`` -- NOT the per-run ``group_id`` UUID, which
|
|
37
|
-
changes every turn. Pane metadata (model / context / tokens)
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
changes every turn. Pane metadata (model / context / tokens), the
|
|
39
|
+
session namer's conversation title, and the best-effort activity
|
|
40
|
+
``message`` are decorative: they never perturb the authoritative state and
|
|
41
|
+
never delay a state edge, session reference, or the final
|
|
42
|
+
``pane.release_agent`` on exit.
|
|
41
43
|
|
|
42
44
|
Handlers are plain sync functions that swallow every argument: the callback
|
|
43
45
|
dispatcher passes hook args positionally and runs sync callbacks happily
|
|
@@ -90,6 +92,11 @@ def _on_turn_end(*_args, **_kw) -> None:
|
|
|
90
92
|
_reporter.on_turn_end()
|
|
91
93
|
|
|
92
94
|
|
|
95
|
+
def _on_post_autosave(*_args, **_kw) -> None:
|
|
96
|
+
# (SessionMetadata,) -- the reporter reads the sidecar itself.
|
|
97
|
+
_reporter.on_post_autosave()
|
|
98
|
+
|
|
99
|
+
|
|
93
100
|
def _on_tool_start(*args, **kwargs):
|
|
94
101
|
# (tool_name, tool_args, context=None). Decorative only -> return None so
|
|
95
102
|
# the tool is never blocked or transformed.
|
|
@@ -127,6 +134,7 @@ if _reporter.active:
|
|
|
127
134
|
register_callback("agent_run_cancel", _on_run_cancel)
|
|
128
135
|
register_callback("interactive_turn_end", _on_turn_end)
|
|
129
136
|
register_callback("interactive_turn_cancel", _on_turn_end)
|
|
137
|
+
register_callback("post_autosave", _on_post_autosave)
|
|
130
138
|
register_callback("pre_tool_call", _on_tool_start)
|
|
131
139
|
register_callback("post_tool_call", _on_tool_complete)
|
|
132
140
|
register_callback("awaiting_user_input", _on_awaiting_user_input)
|
|
@@ -26,12 +26,19 @@ Effective state::
|
|
|
26
26
|
Sub-agents fire the same ``agent_run_start`` / ``agent_run_end`` hooks as the
|
|
27
27
|
root agent, so we refcount active runs (the same pattern the puppy_spinner
|
|
28
28
|
plugin uses) rather than flipping idle when a sub-agent finishes.
|
|
29
|
+
|
|
30
|
+
Beyond state, the reporter propagates the session namer's auto-generated
|
|
31
|
+
conversation title to the pane (presentation title: herdr's pane border and
|
|
32
|
+
the sidebar ``pane`` token). The namer names the session asynchronously
|
|
33
|
+
after each autosave, so a bounded background wait re-reads the sidecar and
|
|
34
|
+
reports the title the moment it lands, without waiting for the next turn.
|
|
29
35
|
"""
|
|
30
36
|
|
|
31
37
|
from __future__ import annotations
|
|
32
38
|
|
|
33
39
|
import logging
|
|
34
40
|
import threading
|
|
41
|
+
import time
|
|
35
42
|
from typing import Optional, Tuple
|
|
36
43
|
|
|
37
44
|
from .client import HerdrClient
|
|
@@ -48,6 +55,11 @@ IDLE = "idle"
|
|
|
48
55
|
THINKING = "thinking"
|
|
49
56
|
AWAITING = "awaiting input"
|
|
50
57
|
|
|
58
|
+
# The namer's model call has its own 60s timeout; the wait for a fresh
|
|
59
|
+
# title must cover that plus queueing slack, then give up.
|
|
60
|
+
_TITLE_WAIT_INTERVAL_S = 2.0
|
|
61
|
+
_TITLE_WAIT_TIMEOUT_S = 90.0
|
|
62
|
+
|
|
51
63
|
|
|
52
64
|
class HerdrReporter:
|
|
53
65
|
"""Thread-safe, dedup-ing bridge from callbacks to :class:`HerdrClient`."""
|
|
@@ -66,6 +78,13 @@ class HerdrReporter:
|
|
|
66
78
|
# Durable session reference (name, pickle_path) — NOT the per-run group_id UUID,
|
|
67
79
|
# which changes every turn and can't identify a resumable session.
|
|
68
80
|
self._session_ref: Optional[Tuple[str, str]] = None
|
|
81
|
+
# The title we believe herdr currently shows for our source (herdr
|
|
82
|
+
# replaces the whole per-source metadata entry per report, so this
|
|
83
|
+
# must always match the last envelope we sent).
|
|
84
|
+
self._reported_title: Optional[str] = None
|
|
85
|
+
# Single-flight background wait for the namer's async title write.
|
|
86
|
+
self._title_wait: Optional[threading.Thread] = None
|
|
87
|
+
self._title_wait_session: Optional[str] = None
|
|
69
88
|
|
|
70
89
|
@property
|
|
71
90
|
def active(self) -> bool:
|
|
@@ -139,6 +158,26 @@ class HerdrReporter:
|
|
|
139
158
|
def on_user_prompt(self, *_ignored) -> None:
|
|
140
159
|
# Ignore the callback's per-run group_id; resolve the durable session.
|
|
141
160
|
self._refresh_session()
|
|
161
|
+
# The title belongs to the session: a resumed or fresh session shows
|
|
162
|
+
# its own title (or none) without waiting for the next turn.
|
|
163
|
+
self._refresh_title()
|
|
164
|
+
|
|
165
|
+
def on_post_autosave(self, *_ignored) -> None:
|
|
166
|
+
"""A session was just saved: report a fresh title, or wait for one.
|
|
167
|
+
|
|
168
|
+
The namer names the conversation asynchronously after this event, so
|
|
169
|
+
a title typically lands seconds later. When the session is still
|
|
170
|
+
unnamed and the namer is enabled, a bounded background wait reports
|
|
171
|
+
the title as soon as it appears. No-op outside herdr.
|
|
172
|
+
"""
|
|
173
|
+
if not self._client.active:
|
|
174
|
+
return
|
|
175
|
+
if sources.current_session_title() is not None:
|
|
176
|
+
self._refresh_title()
|
|
177
|
+
return
|
|
178
|
+
if not sources.naming_enabled():
|
|
179
|
+
return
|
|
180
|
+
self._start_title_wait()
|
|
142
181
|
|
|
143
182
|
def on_run_start(self, *_ignored) -> None:
|
|
144
183
|
with self._lock:
|
|
@@ -190,10 +229,88 @@ class HerdrReporter:
|
|
|
190
229
|
self._emit_metadata()
|
|
191
230
|
|
|
192
231
|
def _emit_metadata(self) -> None:
|
|
193
|
-
"""Compute and enqueue pane metadata. Never holds the reporter lock.
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
232
|
+
"""Compute and enqueue pane metadata. Never holds the reporter lock.
|
|
233
|
+
|
|
234
|
+
The tokens payload and the session title ride one envelope: herdr
|
|
235
|
+
replaces the whole per-source metadata entry on each report, so a
|
|
236
|
+
tokens report that omits the title would silently wipe it.
|
|
237
|
+
"""
|
|
238
|
+
tokens = sources.current_tokens_payload()
|
|
239
|
+
title = sources.current_session_title()
|
|
240
|
+
changed, previous = self._claim_title(title)
|
|
241
|
+
if tokens is None and not changed:
|
|
242
|
+
return
|
|
243
|
+
# Clear only on a set->None transition; when a tokens report is
|
|
244
|
+
# present, its entry replacement clears any stale title for us.
|
|
245
|
+
self._client.report_metadata(
|
|
246
|
+
tokens, title=title, clear_title=changed and title is None
|
|
247
|
+
)
|
|
248
|
+
if changed:
|
|
249
|
+
self._client.set_tab_label(title, expected=previous)
|
|
250
|
+
|
|
251
|
+
# -- session title propagation --------------------------------------
|
|
252
|
+
|
|
253
|
+
def _claim_title(self, title: Optional[str]) -> Tuple[bool, Optional[str]]:
|
|
254
|
+
"""Record ``title`` as the herdr-side value.
|
|
255
|
+
|
|
256
|
+
Returns ``(changed, previous)`` -- ``previous`` is the value herdr
|
|
257
|
+
showed before this claim, so a clear can tell the tab-label restore
|
|
258
|
+
what label it should find there. Both title paths (turn-end
|
|
259
|
+
metadata and title-only refresh) go through here, so
|
|
260
|
+
``_reported_title`` is the single source of truth for what herdr
|
|
261
|
+
currently shows for our source.
|
|
262
|
+
"""
|
|
263
|
+
with self._lock:
|
|
264
|
+
previous = self._reported_title
|
|
265
|
+
if title == previous:
|
|
266
|
+
return False, previous
|
|
267
|
+
self._reported_title = title
|
|
268
|
+
return True, previous
|
|
269
|
+
|
|
270
|
+
def _refresh_title(self) -> bool:
|
|
271
|
+
"""Report the current session's title (or its absence). Title-only.
|
|
272
|
+
|
|
273
|
+
Returns True when a report was enqueued. Safe to call whenever:
|
|
274
|
+
deduped by :meth:`_claim_title`.
|
|
275
|
+
"""
|
|
276
|
+
title = sources.current_session_title()
|
|
277
|
+
changed, previous = self._claim_title(title)
|
|
278
|
+
if not changed:
|
|
279
|
+
return False
|
|
280
|
+
self._client.report_metadata(None, title=title, clear_title=(title is None))
|
|
281
|
+
self._client.set_tab_label(title, expected=previous)
|
|
282
|
+
return True
|
|
283
|
+
|
|
284
|
+
def _start_title_wait(self) -> None:
|
|
285
|
+
"""Arm a bounded, session-pinned background wait for a fresh title.
|
|
286
|
+
|
|
287
|
+
Single-flight: at most one wait at a time. The wait stops on title
|
|
288
|
+
arrival, session change, shutdown (daemon thread), or timeout.
|
|
289
|
+
"""
|
|
290
|
+
session = sources.current_session_name()
|
|
291
|
+
with self._lock:
|
|
292
|
+
wait = self._title_wait
|
|
293
|
+
if wait is not None and wait.is_alive():
|
|
294
|
+
return
|
|
295
|
+
wait = threading.Thread(
|
|
296
|
+
target=self._title_wait_loop, name="herdr-title-wait", daemon=True
|
|
297
|
+
)
|
|
298
|
+
self._title_wait = wait
|
|
299
|
+
self._title_wait_session = session
|
|
300
|
+
wait.start()
|
|
301
|
+
|
|
302
|
+
def _title_wait_loop(self) -> None:
|
|
303
|
+
"""Re-check the sidecar until the title lands, the session changes,
|
|
304
|
+
or the timeout elapses. Runs on its own daemon thread; every step
|
|
305
|
+
is fail-soft."""
|
|
306
|
+
deadline = time.monotonic() + _TITLE_WAIT_TIMEOUT_S
|
|
307
|
+
pinned = self._title_wait_session
|
|
308
|
+
while time.monotonic() < deadline:
|
|
309
|
+
time.sleep(_TITLE_WAIT_INTERVAL_S)
|
|
310
|
+
if sources.current_session_name() != pinned:
|
|
311
|
+
return # the new prompt's refresh owns the new session's title
|
|
312
|
+
if self._refresh_title():
|
|
313
|
+
return # title landed (or its absence was reported)
|
|
197
314
|
|
|
198
315
|
def on_awaiting_user_input(self, awaiting: bool, *, notify: bool = True) -> None:
|
|
199
316
|
"""Track an interactive wait, notifying only when requested."""
|
|
@@ -203,6 +320,14 @@ class HerdrReporter:
|
|
|
203
320
|
self._sync()
|
|
204
321
|
|
|
205
322
|
def on_shutdown(self) -> None:
|
|
323
|
+
# If we relabelled the workspace tab, restore its original label
|
|
324
|
+
# first: the client drains the tab job ahead of the release on its
|
|
325
|
+
# worker. A title currently displayed means the tab may be ours;
|
|
326
|
+
# no title ever shown means no tab job is needed at all.
|
|
327
|
+
with self._lock:
|
|
328
|
+
expected = self._reported_title
|
|
329
|
+
if expected is not None:
|
|
330
|
+
self._client.set_tab_label(None, expected=expected)
|
|
206
331
|
# Release pane authority directly (no intermediate idle report).
|
|
207
332
|
# release_and_close() is idempotent and bounded, so calling it from both
|
|
208
333
|
# session_end and shutdown can never delay process exit.
|