Feature: TUI normal text input dispatches to LLM via A2A facade As a user of the CleverAgents TUI I want my normal text messages to be sent to an LLM actor So that I can have a real conversation through the TUI interface Background: Given the TUI app is initialised with a mock A2A facade and session Scenario: Normal text input dispatches to LLM and renders response When I submit the text "hello there" Then the facade should have received a message/send request And the conversation should show the assistant response Scenario: Dispatch passes active persona actor as override When I dispatch "hello there" overriding actor with "openai/gpt-4o" Then the facade should have received a message/send request with actor "openai/gpt-4o" Scenario: Normal text with no facade falls back to preview mode Given the TUI app is initialised without a facade When I submit the text "hello there" Then the conversation should show the preview text "hello there" Scenario: LLM dispatch handles SessionActorNotConfiguredError gracefully Given the facade raises SessionActorNotConfiguredError When I submit the text "hello there" Then the conversation should show the no-actor error message Scenario: LLM dispatch handles generic facade error gracefully Given the facade returns an A2A error response When I submit the text "hello there" Then the conversation should show an error message Scenario: _create_tui_session returns real session_id from service Given a mock session service that returns session_id "abc-123" When I call _create_tui_session with that service Then the returned session_id should be "abc-123" Scenario: _create_tui_session falls back to default when service unavailable Given the session service raises an exception When I call _create_tui_session with that service Then the returned session_id should be "default" Scenario: LLM dispatch handles SessionNotFoundError gracefully Given the facade raises SessionNotFoundError When I submit the text "hello" Then the conversation should show a session-not-found error message Scenario: LLM dispatch handles DatabaseError gracefully Given the facade raises DatabaseError When I submit the text "hello" Then the conversation should show a database error message Scenario: Worker error is surfaced in the conversation widget When the worker completes with error "network timeout" Then the formatted outcome should show an error message Scenario: Worker success result is passed through unchanged When the worker completes with result "You: hi\n\nAssistant: hello" Then the formatted outcome should be "You: hi\n\nAssistant: hello" Scenario: Empty assistant response shows fallback text Given the TUI app is initialised with a facade that returns empty response When I submit the text "hello" Then the conversation should show "(no response)" Scenario: Rich markup in user input is escaped before storage in transcript Given the TUI app is initialised with a mock A2A facade and session When I submit the text "[bold]attack[/bold]" Then the transcript entry should have markup escaped Scenario: _format_worker_outcome re-raises KeyboardInterrupt When the worker completes with a KeyboardInterrupt error Then _format_worker_outcome should re-raise it Scenario: _format_worker_outcome re-raises SystemExit When the worker completes with a SystemExit error Then _format_worker_outcome should re-raise it Scenario: _format_worker_outcome returns None when both result and error are None When the worker completes with neither result nor error Then the formatted outcome should be None Scenario: _build_tui_facade returns None when facade construction fails When _build_tui_facade is called with a broken container Then the returned facade should be None Scenario: _create_tui_session binds active persona actor at session creation Given a mock session service that returns session_id "abc-123" And a persona state with active actor "anthropic/claude-4-sonnet" When I call _create_tui_session with that service and persona state Then the session should have been created with actor "anthropic/claude-4-sonnet"