i forgot too commit
All checks were successful
Enterprise AI Code Review / ai-review (pull_request) Successful in 38s
All checks were successful
Enterprise AI Code Review / ai-review (pull_request) Successful in 38s
This commit is contained in:
248
cli/formatters.py
Normal file
248
cli/formatters.py
Normal file
@@ -0,0 +1,248 @@
|
||||
"""Terminal formatting for CLI responses."""
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Any
|
||||
|
||||
try:
|
||||
from rich.console import Console
|
||||
from rich.markdown import Markdown
|
||||
from rich.panel import Panel
|
||||
from rich.text import Text
|
||||
|
||||
RICH_AVAILABLE = True
|
||||
except ImportError:
|
||||
RICH_AVAILABLE = False
|
||||
|
||||
|
||||
class ResponseFormatter:
|
||||
"""Formats API responses for terminal display."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
show_mood: bool = True,
|
||||
show_relationship: bool = False,
|
||||
show_facts: bool = False,
|
||||
show_timestamps: bool = False,
|
||||
use_rich: bool = True,
|
||||
):
|
||||
"""Initialize formatter.
|
||||
|
||||
Args:
|
||||
show_mood: Show mood information
|
||||
show_relationship: Show relationship information
|
||||
show_facts: Show extracted facts
|
||||
show_timestamps: Show timestamps
|
||||
use_rich: Use rich formatting (if available)
|
||||
"""
|
||||
self.show_mood = show_mood
|
||||
self.show_relationship = show_relationship
|
||||
self.show_facts = show_facts
|
||||
self.show_timestamps = show_timestamps
|
||||
self.use_rich = use_rich and RICH_AVAILABLE
|
||||
|
||||
if self.use_rich:
|
||||
self.console = Console()
|
||||
|
||||
def format_message(self, role: str, content: str, timestamp: str | None = None) -> str:
|
||||
"""Format a chat message.
|
||||
|
||||
Args:
|
||||
role: Message role (user/assistant)
|
||||
content: Message content
|
||||
timestamp: Optional timestamp
|
||||
|
||||
Returns:
|
||||
str: Formatted message
|
||||
"""
|
||||
if self.use_rich:
|
||||
return self._format_message_rich(role, content, timestamp)
|
||||
return self._format_message_plain(role, content, timestamp)
|
||||
|
||||
def _format_message_plain(self, role: str, content: str, timestamp: str | None = None) -> str:
|
||||
"""Format message in plain text.
|
||||
|
||||
Args:
|
||||
role: Message role
|
||||
content: Message content
|
||||
timestamp: Optional timestamp
|
||||
|
||||
Returns:
|
||||
str: Formatted message
|
||||
"""
|
||||
prefix = "You" if role == "user" else "Bartender"
|
||||
lines = [f"{prefix}: {content}"]
|
||||
|
||||
if timestamp and self.show_timestamps:
|
||||
try:
|
||||
dt = datetime.fromisoformat(timestamp.replace("Z", "+00:00"))
|
||||
time_str = dt.strftime("%H:%M:%S")
|
||||
lines.append(f" [{time_str}]")
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return "\n".join(lines)
|
||||
|
||||
def _format_message_rich(self, role: str, content: str, timestamp: str | None = None) -> None:
|
||||
"""Format message using rich.
|
||||
|
||||
Args:
|
||||
role: Message role
|
||||
content: Message content
|
||||
timestamp: Optional timestamp
|
||||
"""
|
||||
if role == "user":
|
||||
style = "bold cyan"
|
||||
prefix = "You"
|
||||
else:
|
||||
style = "bold green"
|
||||
prefix = "Bartender"
|
||||
|
||||
text = Text()
|
||||
text.append(f"{prefix}: ", style=style)
|
||||
text.append(content)
|
||||
|
||||
if timestamp and self.show_timestamps:
|
||||
try:
|
||||
dt = datetime.fromisoformat(timestamp.replace("Z", "+00:00"))
|
||||
time_str = dt.strftime("%H:%M:%S")
|
||||
text.append(f"\n [{time_str}]", style="dim")
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
self.console.print(text)
|
||||
|
||||
def format_response(self, response: dict[str, Any]) -> str:
|
||||
"""Format a chat response with metadata.
|
||||
|
||||
Args:
|
||||
response: API response
|
||||
|
||||
Returns:
|
||||
str: Formatted response
|
||||
"""
|
||||
if self.use_rich:
|
||||
return self._format_response_rich(response)
|
||||
return self._format_response_plain(response)
|
||||
|
||||
def _format_response_plain(self, response: dict[str, Any]) -> str:
|
||||
"""Format response in plain text.
|
||||
|
||||
Args:
|
||||
response: API response
|
||||
|
||||
Returns:
|
||||
str: Formatted response
|
||||
"""
|
||||
lines = [f"Bartender: {response['response']}"]
|
||||
|
||||
# Add metadata
|
||||
metadata = []
|
||||
|
||||
if self.show_mood and response.get("mood"):
|
||||
mood = response["mood"]
|
||||
metadata.append(f"Mood: {mood['label']}")
|
||||
|
||||
if self.show_relationship and response.get("relationship"):
|
||||
rel = response["relationship"]
|
||||
metadata.append(f"Relationship: {rel['level']} ({rel['score']})")
|
||||
|
||||
if self.show_facts and response.get("extracted_facts"):
|
||||
facts = response["extracted_facts"]
|
||||
if facts:
|
||||
metadata.append(f"Facts learned: {len(facts)}")
|
||||
|
||||
if metadata:
|
||||
lines.append(" " + " | ".join(metadata))
|
||||
|
||||
return "\n".join(lines)
|
||||
|
||||
def _format_response_rich(self, response: dict[str, Any]) -> None:
|
||||
"""Format response using rich.
|
||||
|
||||
Args:
|
||||
response: API response
|
||||
"""
|
||||
# Main response
|
||||
text = Text()
|
||||
text.append("Bartender: ", style="bold green")
|
||||
text.append(response["response"])
|
||||
self.console.print(text)
|
||||
|
||||
# Metadata panel
|
||||
metadata_lines = []
|
||||
|
||||
if self.show_mood and response.get("mood"):
|
||||
mood = response["mood"]
|
||||
mood_line = Text()
|
||||
mood_line.append("Mood: ", style="dim")
|
||||
mood_line.append(mood["label"], style="yellow")
|
||||
mood_line.append(
|
||||
f" (v:{mood['valence']:.1f}, a:{mood['arousal']:.1f}, i:{mood['intensity']:.1f})",
|
||||
style="dim",
|
||||
)
|
||||
metadata_lines.append(mood_line)
|
||||
|
||||
if self.show_relationship and response.get("relationship"):
|
||||
rel = response["relationship"]
|
||||
rel_line = Text()
|
||||
rel_line.append("Relationship: ", style="dim")
|
||||
rel_line.append(f"{rel['level']} ({rel['score']})", style="cyan")
|
||||
rel_line.append(f" | {rel['interactions_count']} interactions", style="dim")
|
||||
metadata_lines.append(rel_line)
|
||||
|
||||
if self.show_facts and response.get("extracted_facts"):
|
||||
facts = response["extracted_facts"]
|
||||
if facts:
|
||||
facts_line = Text()
|
||||
facts_line.append("Facts learned: ", style="dim")
|
||||
facts_line.append(f"{len(facts)}", style="magenta")
|
||||
metadata_lines.append(facts_line)
|
||||
|
||||
if metadata_lines:
|
||||
self.console.print()
|
||||
for line in metadata_lines:
|
||||
self.console.print(" ", line)
|
||||
|
||||
def format_history_message(self, message: dict[str, Any]) -> str:
|
||||
"""Format a history message.
|
||||
|
||||
Args:
|
||||
message: History message
|
||||
|
||||
Returns:
|
||||
str: Formatted message
|
||||
"""
|
||||
return self.format_message(message["role"], message["content"], message.get("timestamp"))
|
||||
|
||||
def print_error(self, message: str) -> None:
|
||||
"""Print an error message.
|
||||
|
||||
Args:
|
||||
message: Error message
|
||||
"""
|
||||
if self.use_rich:
|
||||
self.console.print(f"[bold red]Error:[/bold red] {message}")
|
||||
else:
|
||||
print(f"Error: {message}")
|
||||
|
||||
def print_info(self, message: str) -> None:
|
||||
"""Print an info message.
|
||||
|
||||
Args:
|
||||
message: Info message
|
||||
"""
|
||||
if self.use_rich:
|
||||
self.console.print(f"[dim]{message}[/dim]")
|
||||
else:
|
||||
print(message)
|
||||
|
||||
def print_success(self, message: str) -> None:
|
||||
"""Print a success message.
|
||||
|
||||
Args:
|
||||
message: Success message
|
||||
"""
|
||||
if self.use_rich:
|
||||
self.console.print(f"[bold green]✓[/bold green] {message}")
|
||||
else:
|
||||
print(f"✓ {message}")
|
||||
Reference in New Issue
Block a user