Repository: gradio-app/gradio
File: gradio/chat_interface.py (Python)

Code before:
            title = title[:40] + "..."
        return title or "Conversation"

    def make_serializable(self, obj: Any) -> dict | list | str:
        if isinstance(obj, list):
            return [self.make_serializable(item) for item in obj]
        elif isinstance(obj, dict):
            return {k: self.make_serializable(v) for k, v in obj.items()}
        elif hasattr(obj, "get_config"):
            try:
                if hasattr(obj, "value"):
                    return obj.value
            except Exception:
                return str(obj)
        return obj

    def _save_conversation(
        self,
        index: int | None,
        conversation: list[MessageDict],
        saved_conversations: list[list[MessageDict]],
    ):
        if self.save_history:
            serializable_conversation = self.make_serializable(conversation)
            if index is not None:
                saved_conversations[index] = cast(
                    list[MessageDict], serializable_conversation
                )
            else:
                saved_conversations = saved_conversations or []
                saved_conversations.insert(
                    0, cast(list[MessageDict], serializable_conversation)
                )
                index = 0
        return index, saved_conversations

    def _delete_conversation(
        self,
        index: int | None,
        saved_conversations: list[list[MessageDict]],
    ):
        if index is not None:
            saved_conversations.pop(index)
        return None, saved_conversations

    def _load_chat_history(self, conversations):
        return Dataset(
            samples=[
                [self._generate_chat_title(conv)]
                for conv in conversations or []
                if conv

Review comment (suggestion):
This casting is not ideal as it'll mask any typing issues, would be better if we ensured that make_serializable returned a list[MessageDict].

Code after:
            title = title[:40] + "..."
        return title or "Conversation"

    @staticmethod
    def serialize_components(conversation: list[MessageDict]) -> list[MessageDict]:
        def inner(obj: Any) -> Any:
            if isinstance(obj, list):
                return [inner(item) for item in obj]
            elif isinstance(obj, dict):
                return {k: inner(v) for k, v in obj.items()}
            elif isinstance(obj, Component):
                return obj.value
            return obj

        return inner(conversation)

    def _save_conversation(
        self,
        index: int | None,
        conversation: list[MessageDict],
        saved_conversations: list[list[MessageDict]],
    ):
        if self.save_history:
            serialized_conversation = self.serialize_components(conversation)
            if index is not None:
                saved_conversations[index] = serialized_conversation
            else:
                saved_conversations = saved_conversations or []
                saved_conversations.insert(0, serialized_conversation)
                index = 0
        return index, saved_conversations

    def _delete_conversation(
        self,
        index: int | None,
        saved_conversations: list[list[MessageDict]],
    ):
        if index is not None:
            saved_conversations.pop(index)
        return None, saved_conversations

    def _load_chat_history(self, conversations):
        return Dataset(
            samples=[
                [self._generate_chat_title(conv)]
                for conv in conversations or []
                if conv
            ]
        )

    def _load_conversation(