chore: import upstream snapshot with attribution
dotnet-build-and-test / dotnet-test-functions (push) Has been cancelled
dotnet-build-and-test / paths-filter (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Debug, windows-latest, net9.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Release, ubuntu-latest, net10.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Release, ubuntu-latest, net8.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Release, windows-latest, net472) (push) Has been cancelled
dotnet-build-and-test / dotnet-test (Release, integration, true, ubuntu-latest, net10.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-test (Release, integration, true, windows-latest, net472) (push) Has been cancelled
dotnet-build-and-test / dotnet-foundry-hosted-it (push) Has been cancelled
dotnet-build-and-test / dotnet-build-and-test-check (push) Has been cancelled
dotnet-build-and-test / Integration Test Report (push) Has been cancelled
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
dotnet-build-and-test / dotnet-test-functions (push) Has been cancelled
dotnet-build-and-test / paths-filter (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Debug, windows-latest, net9.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Release, ubuntu-latest, net10.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Release, ubuntu-latest, net8.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Release, windows-latest, net472) (push) Has been cancelled
dotnet-build-and-test / dotnet-test (Release, integration, true, ubuntu-latest, net10.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-test (Release, integration, true, windows-latest, net472) (push) Has been cancelled
dotnet-build-and-test / dotnet-foundry-hosted-it (push) Has been cancelled
dotnet-build-and-test / dotnet-build-and-test-check (push) Has been cancelled
dotnet-build-and-test / Integration Test Report (push) Has been cancelled
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
# 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("")
|
||||
queued_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 and not self.queued_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]")
|
||||
|
||||
if self.queued_text:
|
||||
parts.append(f"[dim]{self.queued_text}[/dim]")
|
||||
|
||||
return " ".join(parts)
|
||||
Reference in New Issue
Block a user