'
# Initialize markdown with proper extensions
md = markdown.Markdown(extensions=[
'fenced_code',
'tables',
'nl2br',
'sane_lists' # Better list handling
])
# Create a mapping of sender identifiers to players
player_map = {}
for p in players:
if p.team and p.role:
key = f"{p.team}_{p.role}"
if key not in player_map:
player_map[key] = []
player_map[key].append(p)
if p.role == "player":
agent_num = len(player_map[key])
player_map[f"{p.team}_agent_{agent_num}"] = p
for msg in messages:
content = getattr(msg, 'content', '')
if not content or not str(content).strip():
continue
metadata = getattr(msg, 'metadata', {}) or {}
title = metadata.get('title', '') if isinstance(metadata, dict) else ''
sender = metadata.get('sender', '') if isinstance(metadata, dict) else ''
# Find the player for this sender
player = None
team = ''
avatar = 'assets/robot.png'
display_sender = ''
if sender:
sender_lower = sender.lower()
if sender_lower in player_map:
if isinstance(player_map[sender_lower], list):
player = player_map[sender_lower][0]
else:
player = player_map[sender_lower]
if player:
avatar = f"/gradio_api/file={player.avatar}"
display_sender = f"{player.name} ({player.role.title()})"
team = player.team
else:
display_sender = sender.replace('_', ' ').title()
if 'red' in sender_lower:
team = 'red'
elif 'blue' in sender_lower:
team = 'blue'
elif 'judge' in sender_lower:
avatar = "/gradio_api/file=assets/avatars/judge.png"
team = 'judge'
# Determine card class based on team and role
card_class = 'message_card'
if team == 'red':
card_class += ' message_red'
elif team == 'blue':
card_class += ' message_blue'
elif team == 'judge' or 'judge' in sender.lower():
card_class += ' message_judge'
if player and player.role:
if player.role == 'boss':
card_class += ' message_boss'
elif player.role == 'captain':
card_class += ' message_captain'
elif player.role == 'player':
card_class += ' message_agent'
if 'Thinking' in title:
card_class += ' message_thinking'
elif '🛠️' in title or 'tool' in title.lower() or 'Using' in content:
card_class += ' message_tool'
# Extract icon from title if present
icon = ''
clean_title = title
if title:
parts = title.split(' ', 1)
if len(parts) > 1 and regex.match(emoji_pattern, parts[0]):
icon = parts[0]
clean_title = parts[1] if len(parts) > 1 else ''
if not clean_title:
icon = "✉️"
# IMPORTANT: Reset markdown parser and convert content
md.reset()
content_html = md.convert(str(content))
html += f'''
{display_sender}{clean_title or 'Message'}
{icon}
{content_html}
'''
html += '
'
if fireworks_animation:
html = f'{html}{fireworks_animation}'
return html
def generate_team_html(players, starting_team=None, is_human_playing=False):
"""Generate improved team cards with working avatars and starting team indicator"""
role_order = {"boss": 0, "captain": 1, "player": 2}
red_players = sorted(
[p for p in players if p.team == "red"],
key=lambda p: role_order.get(p.role, 99)
)
blue_players = sorted(
[p for p in players if p.team == "blue"],
key=lambda p: role_order.get(p.role, 99)
)
def create_team_card(team_players, team_color, is_starting):
team_name = team_color.upper()
emoji = "🔴" if team_color == "red" else "🔵"
# Add starting team badge if applicable
starting_badge = ""
if is_starting:
starting_badge = "
🎯 STARTING TEAM
"
else:
starting_badge = "
⚔️ OPPONENT TEAM
"
players_html = ""
for p in team_players:
role_badge = f"{p.role.upper()}"
# Use Gradio's file serving path
avatar_path = f"/gradio_api/file={p.avatar}"
human_indicator = ""
if not is_human_playing:
if p.role == "boss":
human_indicator = f"""
"""
if p.role == "boss" and p.model_name == "Human brain":
human_indicator = "👤 HUMAN PLAYER"
players_html += f"""