mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
bad05a2bdc
* Add initial harness console for python * Add textual to project * Add planning and approval flows with list selector * Address PR comments * Fix list selection bug * Fix PR #6312 round 2 review comments - Escape untrusted agent text with rich.markup.escape() in observers (text_output, planning_output, reasoning_display) to prevent markup injection - Remove non-functional 'Always approve' choices from tool_approval.py (framework lacks CreateAlwaysApproveToolResponse support) - Remove textual from root pyproject.toml dev deps (sample-specific) - Add PEP 723 inline script metadata to harness_research.py - Narrow except Exception to except NoMatches in list_selection.py Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix build error * Fix build errors --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
67 lines
2.2 KiB
Python
67 lines
2.2 KiB
Python
# Copyright (c) Microsoft. All rights reserved.
|
|
|
|
"""Agent status widget with spinner animation and usage statistics."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from textual.reactive import reactive
|
|
from textual.widgets import Static
|
|
|
|
|
|
class AgentStatus(Static):
|
|
"""Agent status bar with animated spinner and token usage display.
|
|
|
|
Displays an animated braille pattern spinner when the agent is active,
|
|
along with token usage statistics. The component automatically updates
|
|
the spinner animation at ~10fps for smooth visual feedback.
|
|
|
|
Attributes:
|
|
show_spinner: Whether to display the animated spinner.
|
|
usage_text: Token usage text to display (e.g., "1.2K in / 856 out").
|
|
"""
|
|
|
|
# Braille pattern spinner frames for smooth animation
|
|
SPINNER_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"]
|
|
|
|
show_spinner: reactive[bool] = reactive(False)
|
|
usage_text: reactive[str] = reactive("")
|
|
|
|
def __init__(self, **kwargs) -> None:
|
|
"""Initialize the agent status widget."""
|
|
super().__init__(**kwargs)
|
|
self._spinner_index = 0
|
|
|
|
def on_mount(self) -> None:
|
|
"""Start the spinner animation timer when the widget is mounted."""
|
|
# Update spinner at ~10fps (every 0.1 seconds)
|
|
self.set_interval(0.1, self._advance_spinner)
|
|
|
|
def _advance_spinner(self) -> None:
|
|
"""Advance the spinner to the next frame."""
|
|
if self.show_spinner:
|
|
self._spinner_index = (self._spinner_index + 1) % len(self.SPINNER_FRAMES)
|
|
self.refresh()
|
|
|
|
def render(self) -> str:
|
|
"""Render the status bar with spinner and usage text.
|
|
|
|
Returns:
|
|
Formatted string with Rich markup for spinner and usage display.
|
|
"""
|
|
if not self.show_spinner and not self.usage_text:
|
|
return ""
|
|
|
|
parts = []
|
|
|
|
if self.show_spinner:
|
|
frame = self.SPINNER_FRAMES[self._spinner_index]
|
|
parts.append(f"[cyan]{frame}[/cyan]")
|
|
else:
|
|
# Keep consistent spacing when spinner is off
|
|
parts.append(" ")
|
|
|
|
if self.usage_text:
|
|
parts.append(f"[dim]{self.usage_text}[/dim]")
|
|
|
|
return " ".join(parts)
|