mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-01-21 13:58:15 +00:00
Compare commits
3 Commits
devin/1768
...
devin/1752
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
352b213f7f | ||
|
|
07f4e47bb6 | ||
|
|
20cdc92142 |
@@ -120,6 +120,7 @@ class EventListener(BaseEventListener):
|
|||||||
"completed",
|
"completed",
|
||||||
final_string_output,
|
final_string_output,
|
||||||
)
|
)
|
||||||
|
self.formatter.stop_live()
|
||||||
|
|
||||||
@crewai_event_bus.on(CrewKickoffFailedEvent)
|
@crewai_event_bus.on(CrewKickoffFailedEvent)
|
||||||
def on_crew_failed(source, event: CrewKickoffFailedEvent):
|
def on_crew_failed(source, event: CrewKickoffFailedEvent):
|
||||||
@@ -262,6 +263,7 @@ class EventListener(BaseEventListener):
|
|||||||
self.formatter.update_flow_status(
|
self.formatter.update_flow_status(
|
||||||
self.formatter.current_flow_tree, event.flow_name, source.flow_id
|
self.formatter.current_flow_tree, event.flow_name, source.flow_id
|
||||||
)
|
)
|
||||||
|
self.formatter.stop_live()
|
||||||
|
|
||||||
@crewai_event_bus.on(MethodExecutionStartedEvent)
|
@crewai_event_bus.on(MethodExecutionStartedEvent)
|
||||||
def on_method_execution_started(source, event: MethodExecutionStartedEvent):
|
def on_method_execution_started(source, event: MethodExecutionStartedEvent):
|
||||||
|
|||||||
@@ -1753,3 +1753,9 @@ class ConsoleFormatter:
|
|||||||
Attempts=f"{retry_count + 1}",
|
Attempts=f"{retry_count + 1}",
|
||||||
)
|
)
|
||||||
self.print_panel(content, "🛡️ Guardrail Failed", "red")
|
self.print_panel(content, "🛡️ Guardrail Failed", "red")
|
||||||
|
|
||||||
|
def stop_live(self) -> None:
|
||||||
|
"""Stop and clear any active Live session to restore normal terminal output."""
|
||||||
|
if self._live:
|
||||||
|
self._live.stop()
|
||||||
|
self._live = None
|
||||||
|
|||||||
54
tests/test_rich_live_cleanup.py
Normal file
54
tests/test_rich_live_cleanup.py
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
from unittest.mock import patch
|
||||||
|
from rich.tree import Tree
|
||||||
|
from crewai.utilities.events.utils.console_formatter import ConsoleFormatter
|
||||||
|
from crewai.utilities.events.event_listener import EventListener
|
||||||
|
|
||||||
|
|
||||||
|
class TestRichLiveCleanup:
|
||||||
|
"""Test that Rich Live sessions are properly cleaned up after CrewAI operations."""
|
||||||
|
|
||||||
|
def test_logging_works_after_tree_rendering(self):
|
||||||
|
"""Test that logging output appears after tree rendering with proper cleanup."""
|
||||||
|
formatter = ConsoleFormatter()
|
||||||
|
|
||||||
|
tree = Tree("Test Flow")
|
||||||
|
formatter.print(tree)
|
||||||
|
|
||||||
|
assert formatter._live is not None
|
||||||
|
|
||||||
|
formatter.stop_live()
|
||||||
|
|
||||||
|
assert formatter._live is None
|
||||||
|
|
||||||
|
with patch.object(formatter.console, 'print') as mock_print:
|
||||||
|
formatter.print("This should appear immediately")
|
||||||
|
mock_print.assert_called_once_with("This should appear immediately")
|
||||||
|
|
||||||
|
def test_event_listener_cleanup_integration(self):
|
||||||
|
"""Test that EventListener properly cleans up Live sessions."""
|
||||||
|
event_listener = EventListener()
|
||||||
|
formatter = event_listener.formatter
|
||||||
|
|
||||||
|
tree = Tree("Test Crew")
|
||||||
|
formatter.print(tree)
|
||||||
|
assert formatter._live is not None
|
||||||
|
|
||||||
|
formatter.stop_live()
|
||||||
|
assert formatter._live is None
|
||||||
|
|
||||||
|
def test_stop_live_restores_normal_output(self):
|
||||||
|
"""Test that stop_live properly restores normal console output behavior."""
|
||||||
|
formatter = ConsoleFormatter()
|
||||||
|
|
||||||
|
tree = Tree("Test Tree")
|
||||||
|
formatter.print(tree)
|
||||||
|
|
||||||
|
assert formatter._live is not None
|
||||||
|
|
||||||
|
formatter.stop_live()
|
||||||
|
|
||||||
|
assert formatter._live is None
|
||||||
|
|
||||||
|
with patch.object(formatter.console, 'print') as mock_print:
|
||||||
|
formatter.print("Normal output")
|
||||||
|
mock_print.assert_called_once_with("Normal output")
|
||||||
@@ -114,3 +114,38 @@ class TestConsoleFormatterPauseResume:
|
|||||||
|
|
||||||
assert hasattr(formatter, '_live_paused')
|
assert hasattr(formatter, '_live_paused')
|
||||||
assert not formatter._live_paused
|
assert not formatter._live_paused
|
||||||
|
|
||||||
|
def test_stop_live_with_active_session(self):
|
||||||
|
"""Test stopping Live session when one is active."""
|
||||||
|
formatter = ConsoleFormatter()
|
||||||
|
|
||||||
|
mock_live = MagicMock(spec=Live)
|
||||||
|
formatter._live = mock_live
|
||||||
|
|
||||||
|
formatter.stop_live()
|
||||||
|
|
||||||
|
mock_live.stop.assert_called_once()
|
||||||
|
assert formatter._live is None
|
||||||
|
|
||||||
|
def test_stop_live_with_no_session(self):
|
||||||
|
"""Test stopping Live session when none exists."""
|
||||||
|
formatter = ConsoleFormatter()
|
||||||
|
|
||||||
|
formatter._live = None
|
||||||
|
|
||||||
|
formatter.stop_live()
|
||||||
|
|
||||||
|
assert formatter._live is None
|
||||||
|
|
||||||
|
def test_stop_live_multiple_calls(self):
|
||||||
|
"""Test multiple calls to stop_live are safe."""
|
||||||
|
formatter = ConsoleFormatter()
|
||||||
|
|
||||||
|
mock_live = MagicMock(spec=Live)
|
||||||
|
formatter._live = mock_live
|
||||||
|
|
||||||
|
formatter.stop_live()
|
||||||
|
formatter.stop_live()
|
||||||
|
|
||||||
|
mock_live.stop.assert_called_once()
|
||||||
|
assert formatter._live is None
|
||||||
|
|||||||
Reference in New Issue
Block a user