""" Interactive Chat Display Type Renders either a live chat panel (when conversation data is null/empty) or a completed dialogue (when conversation data is populated). Before the annotator finishes chatting, this shows the chat UI. After clicking "Finish & Annotate", the route writes the conversation into the item data, and this display renders the completed conversation using DialogueDisplay (which supports per-turn ratings). """ import html from typing import Dict, Any, List from .base import BaseDisplay from .dialogue_display import DialogueDisplay # Reuse the dialogue display for rendering completed conversations _dialogue_display = DialogueDisplay() class InteractiveChatDisplay(BaseDisplay): """ Display type for interactive agent chat sessions. When data is null/empty: renders a chat panel placeholder (the actual chat UI is handled by agent-chat.js). When data is populated: delegates to DialogueDisplay for the conversation, which supports per-turn ratings for individual turn annotation. """ name = "interactive_chat" required_fields = ["key"] optional_fields = { "placeholder_text": "Start chatting with the agent to begin the task.", "per_turn_ratings": None, "show_turn_numbers": True, "alternating_shading": True, } description = "Interactive agent chat with post-interaction trace display" supports_span_target = True def render(self, field_config: Dict[str, Any], data: Any) -> str: # If conversation data exists, render as dialogue with per-turn ratings if data: return _dialogue_display.render(field_config, data) # Otherwise render the chat panel container # The actual chat UI is injected by agent-chat.js options = self.get_display_options(field_config) placeholder = html.escape(options.get( "placeholder_text", "Start chatting with the agent to begin the task.", )) field_key = html.escape(field_config.get("key", ""), quote=True) return f'''