@@ -1036,13 +1036,39 @@ def _merge_renderables(renderables: list[Any]) -> Text:
10361036 if i > 0 :
10371037 combined .append ("\n " )
10381038 StrixTUIApp ._append_renderable (combined , item )
1039- return combined
1039+ return StrixTUIApp ._sanitize_text_spans (combined )
1040+
1041+ @staticmethod
1042+ def _sanitize_text_spans (text : Text ) -> Text :
1043+ plain = text .plain
1044+ plain_len = len (plain )
1045+
1046+ if plain_len == 0 or not text .spans :
1047+ return text
1048+
1049+ sanitized = Text (
1050+ plain ,
1051+ style = text .style ,
1052+ justify = text .justify ,
1053+ overflow = text .overflow ,
1054+ no_wrap = text .no_wrap ,
1055+ end = text .end ,
1056+ tab_size = text .tab_size ,
1057+ )
1058+
1059+ for span in text .spans :
1060+ start = max (0 , min (span .start , plain_len ))
1061+ end = max (0 , min (span .end , plain_len ))
1062+ if end > start :
1063+ sanitized .stylize (span .style , start , end )
1064+
1065+ return sanitized
10401066
10411067 @staticmethod
10421068 def _append_renderable (combined : Text , item : Any ) -> None :
10431069 """Recursively append a renderable's text content to a combined Text."""
10441070 if isinstance (item , Text ):
1045- combined .append_text (item )
1071+ combined .append_text (StrixTUIApp . _sanitize_text_spans ( item ) )
10461072 elif isinstance (item , Group ):
10471073 for j , sub in enumerate (item .renderables ):
10481074 if j > 0 :
@@ -1087,7 +1113,7 @@ def _get_rendered_events_content(self, events: list[dict[str, Any]]) -> Any:
10871113 return Text ()
10881114
10891115 if len (renderables ) == 1 and isinstance (renderables [0 ], Text ):
1090- return renderables [0 ]
1116+ return self . _sanitize_text_spans ( renderables [0 ])
10911117
10921118 return self ._merge_renderables (renderables )
10931119
@@ -1123,7 +1149,7 @@ def _render_streaming_content(self, content: str, agent_id: str | None = None) -
11231149 if not renderables :
11241150 result = Text ()
11251151 elif len (renderables ) == 1 and isinstance (renderables [0 ], Text ):
1126- result = renderables [0 ]
1152+ result = self . _sanitize_text_spans ( renderables [0 ])
11271153 else :
11281154 result = self ._merge_renderables (renderables )
11291155
@@ -1215,14 +1241,19 @@ def keymap_styled(keys: list[tuple[str, str]]) -> Text:
12151241 return (Text (" " ), keymap , False )
12161242
12171243 if status == "running" :
1244+ sys_msg = agent_data .get ("system_message" , "" )
12181245 if self ._agent_has_real_activity (agent_id ):
12191246 animated_text = Text ()
12201247 animated_text .append_text (self ._get_sweep_animation (self ._sweep_colors ))
1248+ if sys_msg :
1249+ animated_text .append (sys_msg , style = "dim italic" )
1250+ animated_text .append (" " , style = "dim" )
12211251 animated_text .append ("esc" , style = "white" )
12221252 animated_text .append (" " , style = "dim" )
12231253 animated_text .append ("stop" , style = "dim" )
12241254 return (animated_text , keymap_styled ([("ctrl-q" , "quit" )]), True )
1225- animated_text = self ._get_animated_verb_text (agent_id , "Initializing" )
1255+ msg = sys_msg or "Initializing..."
1256+ animated_text = self ._get_animated_verb_text (agent_id , msg )
12261257 return (animated_text , keymap_styled ([("ctrl-q" , "quit" )]), True )
12271258
12281259 return (None , Text (), False )
@@ -1394,7 +1425,7 @@ def _animate_dots(self) -> None:
13941425 if not has_active_agents :
13951426 has_active_agents = any (
13961427 agent_data .get ("status" , "running" ) in ["running" , "waiting" ]
1397- for agent_data in self .tracer .agents .values ()
1428+ for agent_data in list ( self .tracer .agents .values () )
13981429 )
13991430
14001431 if not has_active_agents :
@@ -1655,12 +1686,26 @@ def _render_chat_content(self, msg_data: dict[str, Any]) -> Any:
16551686 content = msg_data .get ("content" , "" )
16561687 metadata = msg_data .get ("metadata" , {})
16571688
1658- if not content :
1659- return None
1660-
16611689 if role == "user" :
1690+ if not content :
1691+ return None
16621692 return UserMessageRenderer .render_simple (content )
16631693
1694+ renderables = []
1695+
1696+ if "thinking_blocks" in metadata and metadata ["thinking_blocks" ]:
1697+ from strix .interface .tool_components .thinking_renderer import ThinkRenderer
1698+
1699+ for block in metadata ["thinking_blocks" ]:
1700+ thought = block .get ("thinking" , "" )
1701+ if thought :
1702+ renderables .append (
1703+ ThinkRenderer .render ({"args" : {"thought" : thought }}).renderable
1704+ )
1705+
1706+ if not content and not renderables :
1707+ return None
1708+
16641709 if metadata .get ("interrupted" ):
16651710 streaming_result = self ._render_streaming_content (content )
16661711 interrupted_text = Text ()
@@ -1669,7 +1714,18 @@ def _render_chat_content(self, msg_data: dict[str, Any]) -> Any:
16691714 interrupted_text .append ("Interrupted by user" , style = "yellow dim" )
16701715 return self ._merge_renderables ([streaming_result , interrupted_text ])
16711716
1672- return AgentMessageRenderer .render_simple (content )
1717+ if content :
1718+ msg_renderable = AgentMessageRenderer .render_simple (content )
1719+ renderables .append (msg_renderable )
1720+
1721+ if not renderables :
1722+ return None
1723+
1724+ if len (renderables ) == 1 :
1725+ r = renderables [0 ]
1726+ return self ._sanitize_text_spans (r ) if isinstance (r , Text ) else r
1727+
1728+ return self ._merge_renderables (renderables )
16731729
16741730 def _render_tool_content_simple (self , tool_data : dict [str , Any ]) -> Any :
16751731 tool_name = tool_data .get ("tool_name" , "Unknown Tool" )
0 commit comments