diff --git a/agentserver/console/tui_console.py b/agentserver/console/tui_console.py index c5ad4bd..847fbe4 100644 --- a/agentserver/console/tui_console.py +++ b/agentserver/console/tui_console.py @@ -253,8 +253,7 @@ class TUIConsole: self._print_simple(text, style) else: self.output.append(text, style) - if self.app and self.app.is_running: - self.app.invalidate() + self._invalidate() def print_raw(self, text: str, style: str = "output"): """Print without timestamp.""" @@ -262,7 +261,19 @@ class TUIConsole: self._print_simple(text, style) else: self.output.append_raw(text, style) - if self.app and self.app.is_running: + self._invalidate() + + def _invalidate(self): + """Invalidate the app to trigger redraw (thread-safe).""" + if self.app and self.app.is_running: + # Use call_soon_threadsafe for cross-task updates + try: + loop = self.app.loop + if loop and loop.is_running(): + loop.call_soon_threadsafe(self.app.invalidate) + else: + self.app.invalidate() + except Exception: self.app.invalidate() def _print_simple(self, text: str, style: str = "output"): diff --git a/handlers/hello.py b/handlers/hello.py index 0fb086e..e1ab1e6 100644 --- a/handlers/hello.py +++ b/handlers/hello.py @@ -126,15 +126,21 @@ async def handle_response_print(payload: ShoutedResponse, metadata: HandlerMetad Routes output to the TUI console if available, otherwise prints to stdout. """ + console = None try: from run_organism import get_console console = get_console() - if console and hasattr(console, 'on_response'): - console.on_response("response", payload) - return None except ImportError: pass - # Fallback: print to stdout + if console and hasattr(console, 'on_response'): + try: + console.on_response("shouter", payload) + return # Success - don't fall through to print + except Exception as e: + # Debug: show error but continue to fallback + print(f"\n\033[31m[console error] {e}\033[0m") + + # Fallback: print to stdout (only if console not available or failed) print(f"\n\033[36m[response] {payload.message}\033[0m") return None