Skip to content

Commit 70b46ed

Browse files
authored
refactoring(cli/tui): richlog visualizer (#577)
1 parent a37f660 commit 70b46ed

File tree

1 file changed

+21
-31
lines changed

1 file changed

+21
-31
lines changed

openhands_cli/tui/widgets/richlog_visualizer.py

Lines changed: 21 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -538,14 +538,18 @@ def _truncate_for_display(
538538
return ELLIPSIS + text[-(max_length - len(ELLIPSIS)) :]
539539
return text
540540

541+
def _clean_and_truncate(self, text: str, *, from_start: bool = True) -> str:
542+
"""Strip, collapse newlines, truncate, and escape Rich markup for display."""
543+
text = str(text).strip().replace("\n", " ")
544+
text = self._truncate_for_display(text, from_start=from_start)
545+
return self._escape_rich_markup(text)
546+
541547
def _extract_meaningful_title(self, event, fallback_title: str) -> str:
542548
"""Extract a meaningful title from an event, with fallback to truncated
543549
content."""
544550
# For ActionEvents, prefer the LLM-generated summary if available
545551
if hasattr(event, "summary") and event.summary:
546-
summary = str(event.summary).strip().replace("\n", " ")
547-
summary = self._truncate_for_display(summary)
548-
return self._escape_rich_markup(summary)
552+
return self._clean_and_truncate(event.summary)
549553

550554
# Try to extract meaningful information from the event
551555
if hasattr(event, "action") and event.action is not None:
@@ -555,42 +559,33 @@ def _extract_meaningful_title(self, event, fallback_title: str) -> str:
555559

556560
# Try to get specific details based on action type
557561
if hasattr(action, "command") and action.command:
558-
# For command actions, show the command
559-
cmd = str(action.command).strip()
560-
cmd = self._truncate_for_display(cmd)
561-
return f"{action_type}: {self._escape_rich_markup(cmd)}"
562+
return f"{action_type}: {self._clean_and_truncate(action.command)}"
562563
elif hasattr(action, "path") and action.path:
563-
# For file actions, show the path (truncate from start to show filename)
564-
path = str(action.path)
565-
path = self._truncate_for_display(path, from_start=False)
566-
return f"{action_type}: {self._escape_rich_markup(path)}"
564+
# For file actions, truncate from start to show filename
565+
566+
return f"{action_type}: {
567+
self._clean_and_truncate(
568+
action.path,
569+
from_start=False,
570+
)
571+
}"
567572
elif hasattr(action, "content") and action.content:
568-
# For content-based actions, show truncated content
569-
content = str(action.content).strip().replace("\n", " ")
570-
content = self._truncate_for_display(content)
571-
return f"{action_type}: {self._escape_rich_markup(content)}"
573+
return f"{action_type}: {self._clean_and_truncate(action.content)}"
572574
elif hasattr(action, "message") and action.message:
573-
# For message actions, show truncated message
574-
msg = str(action.message).strip().replace("\n", " ")
575-
msg = self._truncate_for_display(msg)
576-
return f"{action_type}: {self._escape_rich_markup(msg)}"
575+
return f"{action_type}: {self._clean_and_truncate(action.message)}"
577576
else:
578577
return f"{action_type} Action"
579578

580579
elif hasattr(event, "observation") and event.observation is not None:
581-
# For ObservationEvents, try to get observation details
582580
obs = event.observation
583581
obs_type = obs.__class__.__name__.replace("Observation", "")
584582

585583
if hasattr(obs, "content") and obs.content:
586-
content = str(obs.content).strip().replace("\n", " ")
587-
content = self._truncate_for_display(content)
588-
return f"{obs_type}: {self._escape_rich_markup(content)}"
584+
return f"{obs_type}: {self._clean_and_truncate(obs.content)}"
589585
else:
590586
return f"{obs_type} Observation"
591587

592588
elif hasattr(event, "llm_message") and event.llm_message is not None:
593-
# For MessageEvents, show truncated message content
594589
msg = event.llm_message
595590
if hasattr(msg, "content") and msg.content:
596591
# Extract text from content list (content is a list of TextContent
@@ -605,16 +600,11 @@ def _extract_meaningful_title(self, event, fallback_title: str) -> str:
605600
else:
606601
content_text = str(msg.content)
607602

608-
content_text = content_text.strip().replace("\n", " ")
609-
content_text = self._truncate_for_display(content_text)
610603
role = "User" if msg.role == "user" else "Agent"
611-
return f"{role}: {self._escape_rich_markup(content_text)}"
604+
return f"{role}: {self._clean_and_truncate(content_text)}"
612605

613606
elif hasattr(event, "message") and event.message:
614-
# For events with direct message attribute
615-
content = str(event.message).strip().replace("\n", " ")
616-
content = self._truncate_for_display(content)
617-
return f"{fallback_title}: {self._escape_rich_markup(content)}"
607+
return f"{fallback_title}: {self._clean_and_truncate(event.message)}"
618608

619609
# If we can't extract meaningful info, try to truncate the visualized content
620610
if hasattr(event, "visualize"):

0 commit comments

Comments
 (0)