mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-01-24 15:48:23 +00:00
Compare commits
4 Commits
devin/1768
...
devin/1755
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d9babfae81 | ||
|
|
2c98d0c1d9 | ||
|
|
ac69573afa | ||
|
|
70104e9651 |
57
simple_test_verbose.py
Normal file
57
simple_test_verbose.py
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Simple test to verify the verbose task name fix works."""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src'))
|
||||||
|
|
||||||
|
from unittest.mock import Mock
|
||||||
|
from crewai.utilities.events.utils.console_formatter import ConsoleFormatter
|
||||||
|
|
||||||
|
def test_task_display_name():
|
||||||
|
"""Test the _get_task_display_name method directly."""
|
||||||
|
print("Testing _get_task_display_name method...")
|
||||||
|
|
||||||
|
formatter = ConsoleFormatter(verbose=True)
|
||||||
|
|
||||||
|
task1 = Mock()
|
||||||
|
task1.name = "Research Market Trends"
|
||||||
|
task1.id = "12345678-1234-5678-9012-123456789abc"
|
||||||
|
|
||||||
|
result1 = formatter._get_task_display_name(task1)
|
||||||
|
print(f"Test 1 - Task with name: {result1}")
|
||||||
|
assert "Research Market Trends" in result1
|
||||||
|
assert "12345678" in result1
|
||||||
|
print("✅ Test 1 passed")
|
||||||
|
|
||||||
|
task2 = Mock()
|
||||||
|
task2.name = None
|
||||||
|
task2.description = "Analyze current market trends and provide insights"
|
||||||
|
task2.id = "87654321-4321-8765-2109-987654321abc"
|
||||||
|
|
||||||
|
result2 = formatter._get_task_display_name(task2)
|
||||||
|
print(f"Test 2 - Task with description: {result2}")
|
||||||
|
assert "Analyze current market trends" in result2
|
||||||
|
assert "87654321" in result2
|
||||||
|
print("✅ Test 2 passed")
|
||||||
|
|
||||||
|
task3 = Mock()
|
||||||
|
task3.name = None
|
||||||
|
task3.description = None
|
||||||
|
task3.id = "abcdef12-3456-7890-abcd-ef1234567890"
|
||||||
|
|
||||||
|
result3 = formatter._get_task_display_name(task3)
|
||||||
|
print(f"Test 3 - Task with ID only: {result3}")
|
||||||
|
assert result3 == "abcdef12-3456-7890-abcd-ef1234567890"
|
||||||
|
print("✅ Test 3 passed")
|
||||||
|
|
||||||
|
print("\n🎉 All tests passed! The verbose task name fix is working correctly.")
|
||||||
|
return True
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
try:
|
||||||
|
test_task_display_name()
|
||||||
|
print("\n✅ Implementation verified successfully!")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"\n❌ Test failed: {e}")
|
||||||
|
sys.exit(1)
|
||||||
@@ -162,7 +162,7 @@ class EventListener(BaseEventListener):
|
|||||||
span = self._telemetry.task_started(crew=source.agent.crew, task=source)
|
span = self._telemetry.task_started(crew=source.agent.crew, task=source)
|
||||||
self.execution_spans[source] = span
|
self.execution_spans[source] = span
|
||||||
self.formatter.create_task_branch(
|
self.formatter.create_task_branch(
|
||||||
self.formatter.current_crew_tree, source.id
|
self.formatter.current_crew_tree, source
|
||||||
)
|
)
|
||||||
|
|
||||||
@crewai_event_bus.on(TaskCompletedEvent)
|
@crewai_event_bus.on(TaskCompletedEvent)
|
||||||
@@ -175,7 +175,7 @@ class EventListener(BaseEventListener):
|
|||||||
|
|
||||||
self.formatter.update_task_status(
|
self.formatter.update_task_status(
|
||||||
self.formatter.current_crew_tree,
|
self.formatter.current_crew_tree,
|
||||||
source.id,
|
source,
|
||||||
source.agent.role,
|
source.agent.role,
|
||||||
"completed",
|
"completed",
|
||||||
)
|
)
|
||||||
@@ -190,7 +190,7 @@ class EventListener(BaseEventListener):
|
|||||||
|
|
||||||
self.formatter.update_task_status(
|
self.formatter.update_task_status(
|
||||||
self.formatter.current_crew_tree,
|
self.formatter.current_crew_tree,
|
||||||
source.id,
|
source,
|
||||||
source.agent.role,
|
source.agent.role,
|
||||||
"failed",
|
"failed",
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -220,14 +220,16 @@ class ConsoleFormatter:
|
|||||||
return tree
|
return tree
|
||||||
|
|
||||||
def create_task_branch(
|
def create_task_branch(
|
||||||
self, crew_tree: Optional[Tree], task_id: str
|
self, crew_tree: Optional[Tree], task: Any
|
||||||
) -> Optional[Tree]:
|
) -> Optional[Tree]:
|
||||||
"""Create and initialize a task branch."""
|
"""Create and initialize a task branch."""
|
||||||
if not self.verbose:
|
if not self.verbose:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
task_display = self._get_task_display_name(task)
|
||||||
|
|
||||||
task_content = Text()
|
task_content = Text()
|
||||||
task_content.append(f"📋 Task: {task_id}", style="yellow bold")
|
task_content.append(f"📋 Task: {task_display}", style="yellow bold")
|
||||||
task_content.append("\nStatus: ", style="white")
|
task_content.append("\nStatus: ", style="white")
|
||||||
task_content.append("Executing Task...", style="yellow dim")
|
task_content.append("Executing Task...", style="yellow dim")
|
||||||
|
|
||||||
@@ -248,7 +250,7 @@ class ConsoleFormatter:
|
|||||||
def update_task_status(
|
def update_task_status(
|
||||||
self,
|
self,
|
||||||
crew_tree: Optional[Tree],
|
crew_tree: Optional[Tree],
|
||||||
task_id: str,
|
task: Any,
|
||||||
agent_role: str,
|
agent_role: str,
|
||||||
status: str = "completed",
|
status: str = "completed",
|
||||||
) -> None:
|
) -> None:
|
||||||
@@ -256,6 +258,9 @@ class ConsoleFormatter:
|
|||||||
if not self.verbose or crew_tree is None:
|
if not self.verbose or crew_tree is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
task_display = self._get_task_display_name(task)
|
||||||
|
task_id = str(task.id)
|
||||||
|
|
||||||
if status == "completed":
|
if status == "completed":
|
||||||
style = "green"
|
style = "green"
|
||||||
status_text = "✅ Completed"
|
status_text = "✅ Completed"
|
||||||
@@ -267,11 +272,11 @@ class ConsoleFormatter:
|
|||||||
|
|
||||||
# Update tree label
|
# Update tree label
|
||||||
for branch in crew_tree.children:
|
for branch in crew_tree.children:
|
||||||
if str(task_id) in str(branch.label):
|
if task_id in str(branch.label):
|
||||||
# Build label without introducing stray blank lines
|
# Build label without introducing stray blank lines
|
||||||
task_content = Text()
|
task_content = Text()
|
||||||
# First line: Task ID
|
# First line: Task name/description
|
||||||
task_content.append(f"📋 Task: {task_id}", style=f"{style} bold")
|
task_content.append(f"📋 Task: {task_display}", style=f"{style} bold")
|
||||||
|
|
||||||
# Second line: Assigned to
|
# Second line: Assigned to
|
||||||
task_content.append("\nAssigned to: ", style="white")
|
task_content.append("\nAssigned to: ", style="white")
|
||||||
@@ -286,7 +291,7 @@ class ConsoleFormatter:
|
|||||||
|
|
||||||
# Show status panel
|
# Show status panel
|
||||||
content = self.create_status_content(
|
content = self.create_status_content(
|
||||||
f"Task {status.title()}", str(task_id), style, Agent=agent_role
|
f"Task {status.title()}", task_display, style, Agent=agent_role
|
||||||
)
|
)
|
||||||
self.print_panel(content, panel_title, style)
|
self.print_panel(content, panel_title, style)
|
||||||
|
|
||||||
@@ -1754,3 +1759,13 @@ 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 _get_task_display_name(self, task: Any) -> str:
|
||||||
|
"""Get display name for a task, with fallback logic."""
|
||||||
|
if hasattr(task, 'name') and task.name:
|
||||||
|
return f"{task.name} (ID: {str(task.id)[:8]}...)"
|
||||||
|
elif hasattr(task, 'description') and task.description:
|
||||||
|
desc = task.description[:50] + "..." if len(task.description) > 50 else task.description
|
||||||
|
return f"{desc} (ID: {str(task.id)[:8]}...)"
|
||||||
|
else:
|
||||||
|
return str(task.id)
|
||||||
|
|||||||
44
test_verbose_fix.py
Normal file
44
test_verbose_fix.py
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Test script to verify verbose output shows task names instead of IDs."""
|
||||||
|
|
||||||
|
from crewai import Agent, Task, Crew
|
||||||
|
|
||||||
|
def test_verbose_output():
|
||||||
|
"""Test that verbose output shows task names instead of UUIDs."""
|
||||||
|
print("Testing verbose output with task names...")
|
||||||
|
|
||||||
|
agent = Agent(
|
||||||
|
role="Research Analyst",
|
||||||
|
goal="Analyze data and provide insights",
|
||||||
|
backstory="You are an experienced data analyst.",
|
||||||
|
verbose=True
|
||||||
|
)
|
||||||
|
|
||||||
|
task = Task(
|
||||||
|
name="Market Research Analysis",
|
||||||
|
description="Research current market trends in AI technology",
|
||||||
|
expected_output="A comprehensive report on AI market trends",
|
||||||
|
agent=agent
|
||||||
|
)
|
||||||
|
|
||||||
|
crew = Crew(
|
||||||
|
agents=[agent],
|
||||||
|
tasks=[task],
|
||||||
|
verbose=True
|
||||||
|
)
|
||||||
|
|
||||||
|
print("Task name:", task.name)
|
||||||
|
print("Task ID:", task.id)
|
||||||
|
print("\nRunning crew with verbose=True...")
|
||||||
|
print("Expected: Should show task name 'Market Research Analysis' instead of UUID")
|
||||||
|
|
||||||
|
try:
|
||||||
|
crew.kickoff()
|
||||||
|
print("\nCrew execution completed successfully!")
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error during execution: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
test_verbose_output()
|
||||||
95
tests/utilities/test_console_formatter_verbose.py
Normal file
95
tests/utilities/test_console_formatter_verbose.py
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
from unittest.mock import Mock, patch
|
||||||
|
from crewai.utilities.events.utils.console_formatter import ConsoleFormatter
|
||||||
|
|
||||||
|
|
||||||
|
class TestConsoleFormatterVerbose:
|
||||||
|
"""Test verbose output functionality in console formatter."""
|
||||||
|
|
||||||
|
def setup_method(self):
|
||||||
|
"""Set up test fixtures."""
|
||||||
|
self.formatter = ConsoleFormatter(verbose=True)
|
||||||
|
|
||||||
|
def test_get_task_display_name_with_name(self):
|
||||||
|
"""Test task display name when task has a name."""
|
||||||
|
task = Mock()
|
||||||
|
task.name = "Research Market Trends"
|
||||||
|
task.id = "12345678-1234-5678-9012-123456789abc"
|
||||||
|
|
||||||
|
result = self.formatter._get_task_display_name(task)
|
||||||
|
assert "Research Market Trends" in result
|
||||||
|
assert "12345678" in result
|
||||||
|
|
||||||
|
def test_get_task_display_name_with_description_only(self):
|
||||||
|
"""Test task display name when task has no name but has description."""
|
||||||
|
task = Mock()
|
||||||
|
task.name = None
|
||||||
|
task.description = "Analyze current market trends and provide insights"
|
||||||
|
task.id = "12345678-1234-5678-9012-123456789abc"
|
||||||
|
|
||||||
|
result = self.formatter._get_task_display_name(task)
|
||||||
|
assert "Analyze current market trends" in result
|
||||||
|
assert "12345678" in result
|
||||||
|
|
||||||
|
def test_get_task_display_name_long_description_truncated(self):
|
||||||
|
"""Test task display name truncates long descriptions."""
|
||||||
|
task = Mock()
|
||||||
|
task.name = None
|
||||||
|
task.description = "This is a very long task description that should be truncated because it exceeds the maximum length"
|
||||||
|
task.id = "12345678-1234-5678-9012-123456789abc"
|
||||||
|
|
||||||
|
result = self.formatter._get_task_display_name(task)
|
||||||
|
assert len(result.split("(ID:")[0].strip()) <= 53
|
||||||
|
assert "..." in result
|
||||||
|
|
||||||
|
def test_get_task_display_name_fallback_to_id(self):
|
||||||
|
"""Test task display name falls back to ID when no name or description."""
|
||||||
|
task = Mock()
|
||||||
|
task.name = None
|
||||||
|
task.description = None
|
||||||
|
task.id = "12345678-1234-5678-9012-123456789abc"
|
||||||
|
|
||||||
|
result = self.formatter._get_task_display_name(task)
|
||||||
|
assert result == "12345678-1234-5678-9012-123456789abc"
|
||||||
|
|
||||||
|
@patch('crewai.utilities.events.utils.console_formatter.ConsoleFormatter.print')
|
||||||
|
def test_create_task_branch_uses_task_name(self, mock_print):
|
||||||
|
"""Test create_task_branch displays task name instead of ID."""
|
||||||
|
task = Mock()
|
||||||
|
task.name = "Write Blog Post"
|
||||||
|
task.id = "12345678-1234-5678-9012-123456789abc"
|
||||||
|
|
||||||
|
crew_tree = Mock()
|
||||||
|
crew_tree.add.return_value = Mock()
|
||||||
|
|
||||||
|
self.formatter.create_task_branch(crew_tree, task)
|
||||||
|
|
||||||
|
call_args = crew_tree.add.call_args[0][0]
|
||||||
|
assert "Write Blog Post" in str(call_args)
|
||||||
|
assert "12345678" in str(call_args)
|
||||||
|
|
||||||
|
@patch('crewai.utilities.events.utils.console_formatter.ConsoleFormatter.print')
|
||||||
|
def test_update_task_status_uses_task_name(self, mock_print):
|
||||||
|
"""Test update_task_status displays task name instead of ID."""
|
||||||
|
task = Mock()
|
||||||
|
task.name = "Data Analysis"
|
||||||
|
task.id = "12345678-1234-5678-9012-123456789abc"
|
||||||
|
|
||||||
|
crew_tree = Mock()
|
||||||
|
branch = Mock()
|
||||||
|
branch.label = "12345678-1234-5678-9012-123456789abc"
|
||||||
|
crew_tree.children = [branch]
|
||||||
|
|
||||||
|
self.formatter.update_task_status(crew_tree, task, "Data Analyst", "completed")
|
||||||
|
|
||||||
|
updated_label = branch.label
|
||||||
|
assert "Data Analysis" in str(updated_label)
|
||||||
|
|
||||||
|
def test_verbose_disabled_returns_none(self):
|
||||||
|
"""Test that methods return None when verbose is disabled."""
|
||||||
|
formatter = ConsoleFormatter(verbose=False)
|
||||||
|
task = Mock()
|
||||||
|
|
||||||
|
result = formatter.create_task_branch(Mock(), task)
|
||||||
|
assert result is None
|
||||||
|
|
||||||
|
formatter.update_task_status(Mock(), task, "Agent", "completed")
|
||||||
Reference in New Issue
Block a user