@@ -502,9 +502,10 @@ def check_output_queue(self):
502502 pass
503503
504504 def handle_output_message (self , msg ):
505- """Route output messages to appropriate handlers."""
506505 msg_type = msg ["type" ]
507506
507+ # Resolve agent_name from coder_uuid for agent-specific status messages
508+ agent_name = self ._resolve_agent_name (msg .get ("coder_uuid" ))
508509 if msg_type == "output" :
509510 container = self ._get_output_container (msg )
510511 container .add_output (msg ["text" ], msg .get ("task_id" ))
@@ -532,15 +533,15 @@ def handle_output_message(self, msg):
532533 container = self ._get_output_container (msg )
533534 container .start_task (msg ["task_id" ], msg ["title" ], msg .get ("task_type" ))
534535 elif msg_type == "confirmation" :
535- self .show_confirmation (msg )
536+ self .show_confirmation (msg , agent_name = agent_name )
536537 elif msg_type == "spinner" :
537- self .update_spinner (msg )
538+ self .update_spinner (msg , agent_name = agent_name )
538539 elif msg_type == "ready_for_input" :
539540 self .enable_input (msg )
540541 footer = self .query_one (MainFooter )
541542 footer .stop_spinner ()
542543 elif msg_type == "error" :
543- self .show_error (msg ["message" ])
544+ self .show_error (msg ["message" ], agent_name = agent_name )
544545 elif msg_type == "cost_update" :
545546 footer = self .query_one (MainFooter )
546547 footer .update_cost (msg .get ("cost" , 0 ))
@@ -563,6 +564,53 @@ def handle_output_message(self, msg):
563564 else :
564565 self ._switch_to_container (target_uuid )
565566
567+ def _resolve_agent_name (self , coder_uuid : str | None ) -> str | None :
568+ """Resolve an agent display name from a coder_uuid.
569+
570+ Returns the sub-agent's name if the coder_uuid belongs to a known
571+ sub-agent. For the primary agent, returns "primary" if sub-agents
572+ exist, otherwise None.
573+
574+ If multiple sub-agents share the same name, disambiguates by
575+ appending the first 3 characters of the UUID in parentheses.
576+ """
577+ if not coder_uuid :
578+ return None
579+ try :
580+ if not self .worker or not self .worker .coder :
581+ return None # Cannot resolve without a coder
582+ from cecli .helpers .agents .service import AgentService
583+
584+ agent_service = AgentService .get_instance (self .worker .coder )
585+ if not agent_service :
586+ return None
587+ primary_uuid = str (agent_service .coder .uuid )
588+ if coder_uuid == primary_uuid :
589+ if agent_service .sub_agents :
590+ return "primary"
591+ return None # Primary agent gets no prefix
592+ if not agent_service .sub_agents :
593+ return None
594+ for info in agent_service .sub_agents .values ():
595+ if not info or not info .coder :
596+ continue
597+ if str (info .coder .uuid ) == coder_uuid :
598+ # Check for duplicate names among sub-agents
599+ name_count = sum (
600+ 1
601+ for i in agent_service .sub_agents .values ()
602+ if i and hasattr (i , "name" ) and i .name == info .name
603+ )
604+ if name_count > 1 :
605+ # Disambiguate with first 3 UUID characters
606+ short_uuid = str (info .coder .uuid )[:3 ]
607+ return f"{ info .name } ({ short_uuid } )"
608+ return info .name
609+ except (AttributeError , ImportError , KeyError ):
610+ # Agent service not available or coder not yet initialized
611+ pass
612+ return None
613+
566614 def add_output (self , text , task_id = None ):
567615 """Add output to the output container."""
568616 output_container = self .query_one ("#output" , OutputContainer )
@@ -601,7 +649,7 @@ def start_task(self, task_id, title, task_type="general"):
601649 output_container = self .query_one ("#output" , OutputContainer )
602650 output_container .start_task (task_id , title , task_type )
603651
604- def show_confirmation (self , msg ):
652+ def show_confirmation (self , msg , agent_name : str | None = None ):
605653 """Show inline confirmation bar."""
606654 # Disable input while confirm bar is active
607655 input_area = self .query_one ("#input" , InputArea )
@@ -623,6 +671,7 @@ def show_confirmation(self, msg):
623671 allow_never = allow_never ,
624672 default = options .get ("default" , "y" ),
625673 explicit_yes_required = options .get ("explicit_yes_required" , False ),
674+ agent_name = agent_name ,
626675 )
627676
628677 def enable_input (self , msg , coder = None ):
@@ -657,24 +706,25 @@ def enable_input(self, msg, coder=None):
657706
658707 input_area .focus ()
659708
660- def update_spinner (self , msg ):
709+ def update_spinner (self , msg , agent_name : str | None = None ):
661710 """Update spinner in footer."""
662711 footer = self .query_one (MainFooter )
663712 action = msg .get ("action" , "start" )
664713
665714 if action == "start" :
666- footer .start_spinner (msg .get ("text" , "" ))
715+ footer .start_spinner (msg .get ("text" , "" ), agent_name = agent_name or "" )
667716 elif action == "update" :
668717 footer .spinner_text = msg .get ("text" , "" )
669718 elif action == "update_suffix" :
670719 footer .spinner_suffix = msg .get ("text" , "" )
671720 elif action == "stop" :
672721 footer .stop_spinner ()
673722
674- def show_error (self , message ):
675- """Show error notification."""
676- status_bar = self .query_one ("#status-bar" , StatusBar )
677- status_bar .show_notification (f"Error: { message } " , severity = "error" , timeout = 10 )
723+ def show_error (self , message , agent_name : str | None = None ):
724+ """Show an error message in the status bar."""
725+ self .status_bar .show_notification (
726+ message , severity = "error" , timeout = 5 , agent_name = agent_name
727+ )
678728
679729 def on_resize (self ) -> None :
680730 file_list = self .query_one ("#file-list" , FileList )
@@ -781,15 +831,21 @@ def on_input_area_submit(self, message: InputArea.Submit):
781831
782832 # Update footer to show processing
783833 footer = self .query_one (MainFooter )
784- footer .start_spinner ("Processing..." )
785834
786835 coder = self .worker .coder
787-
788- if coder :
789- coder .io .start_spinner ("Processing..." )
790-
791836 # Determine which coder is in the foreground for input routing
792837 foreground_coder = AgentService .get_instance (coder ).foreground_coder
838+ coder_uuid = (
839+ str (foreground_coder .uuid )
840+ if foreground_coder and hasattr (foreground_coder , "uuid" )
841+ else None
842+ )
843+ agent_name = self ._resolve_agent_name (coder_uuid )
844+
845+ footer .start_spinner ("Processing..." , agent_name = agent_name or "" )
846+
847+ if coder :
848+ coder .io .start_spinner ("Processing..." , coder_uuid = coder_uuid )
793849
794850 if coder and is_active (getattr (coder .io , "output_task" , None )):
795851 from cecli .helpers .conversation import ConversationService , MessageTag
0 commit comments