"""Status display components for OpenHands CLI TUI."""
from datetime import datetime
from openhands.sdk import BaseConversation
from prompt_toolkit import print_formatted_text
from prompt_toolkit.formatted_text import HTML
from prompt_toolkit.shortcuts import print_container
from prompt_toolkit.widgets import Frame, TextArea
def display_status(
conversation: BaseConversation,
session_start_time: datetime,
) -> None:
"""Display detailed conversation status including metrics and uptime.
Args:
conversation: The conversation to display status for
session_start_time: The session start time for uptime calculation
"""
# Get conversation stats
stats = conversation.conversation_stats.get_combined_metrics()
# Calculate uptime from session start time
now = datetime.now()
diff = now - session_start_time
# Format as hours, minutes, seconds
total_seconds = int(diff.total_seconds())
hours = total_seconds // 3600
minutes = (total_seconds % 3600) // 60
seconds = total_seconds % 60
uptime_str = f"{hours}h {minutes}m {seconds}s"
# Display conversation ID and uptime
print_formatted_text(HTML(f'Conversation ID: {conversation.id}'))
print_formatted_text(HTML(f'Uptime: {uptime_str}'))
print_formatted_text('')
# Calculate token metrics
token_usage = stats.accumulated_token_usage
total_input_tokens = token_usage.prompt_tokens if token_usage else 0
total_output_tokens = token_usage.completion_tokens if token_usage else 0
cache_hits = token_usage.cache_read_tokens if token_usage else 0
cache_writes = token_usage.cache_write_tokens if token_usage else 0
total_tokens = total_input_tokens + total_output_tokens
total_cost = stats.accumulated_cost
# Use prompt_toolkit containers for formatted display
_display_usage_metrics_container(
total_cost,
total_input_tokens,
total_output_tokens,
cache_hits,
cache_writes,
total_tokens
)
def _display_usage_metrics_container(
total_cost: float,
total_input_tokens: int,
total_output_tokens: int,
cache_hits: int,
cache_writes: int,
total_tokens: int
) -> None:
"""Display usage metrics using prompt_toolkit containers."""
# Format values with proper formatting
cost_str = f'${total_cost:.6f}'
input_tokens_str = f'{total_input_tokens:,}'
cache_read_str = f'{cache_hits:,}'
cache_write_str = f'{cache_writes:,}'
output_tokens_str = f'{total_output_tokens:,}'
total_tokens_str = f'{total_tokens:,}'
labels_and_values = [
(' Total Cost (USD):', cost_str),
('', ''),
(' Total Input Tokens:', input_tokens_str),
(' Cache Hits:', cache_read_str),
(' Cache Writes:', cache_write_str),
(' Total Output Tokens:', output_tokens_str),
('', ''),
(' Total Tokens:', total_tokens_str),
]
# Calculate max widths for alignment
max_label_width = max(len(label) for label, _ in labels_and_values)
max_value_width = max(len(value) for _, value in labels_and_values)
# Construct the summary text with aligned columns
summary_lines = [
f'{label:<{max_label_width}} {value:<{max_value_width}}'
for label, value in labels_and_values
]
summary_text = '\n'.join(summary_lines)
container = Frame(
TextArea(
text=summary_text,
read_only=True,
wrap_lines=True,
),
title='Usage Metrics',
)
print_container(container)