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

Code before:
        history.extend(message_dicts)  # type: ignore
        if self.type == "tuples":
            history = self._messages_to_tuples(history)  # type: ignore
        return history

    def _message_as_message_dict(
        self,
        message: MessageDict | Message | str | Component | MultimodalPostprocess | list,
        role: Literal["user", "assistant"],
    ) -> list[MessageDict]:
        """
        Converts a user message, example message, or response from the chat function to a
        list of MessageDict objects that can be appended to the chat history.
        """
        message_dicts = []
        if not isinstance(message, list):
            message = [message]
        for msg in message:
            if isinstance(msg, Message):
                message_dicts.append(msg.model_dump())
            elif isinstance(msg, ChatMessage):
                msg.role = role
                message_dicts.append(
                    dataclasses.asdict(msg, dict_factory=utils.dict_factory)
                )
            elif isinstance(msg, (str, Component)):
                message_dicts.append({"role": role, "content": msg})
            elif (
                isinstance(msg, dict) and "content" in msg
            ):  # in MessageDict format already
                msg["role"] = role
                message_dicts.append(msg)
            else:  # in MultimodalPostprocess format
                for x in msg.get("files", []):
                    if isinstance(x, dict):
                        x = x.get("path")
                    message_dicts.append({"role": role, "content": (x,)})
                if msg["text"] is None or not isinstance(msg["text"], str):
                    pass
                else:
                    message_dicts.append({"role": role, "content": msg["text"]})
        return message_dicts

    async def _submit_fn(
        self,
        message: str | MultimodalPostprocess,
        history: TupleFormat | list[MessageDict],
        *args,
    ) -> tuple:
        inputs = [message, history] + list(args)
        if self.is_async:

Review comment (suggestion):
Very cool PR @freddyaboulton! But why did we remove the call to `special_args`? It's needed for us to handle special typed args such as `gr.Request` correctly in the chat function.

For example, this demo no longer works with this PR:

```py
import gradio as gr

def bot_fn(message, history, request: gr.Request):
    return f"Echo: {request.url}"

gr.ChatInterface(bot_fn, type="messages").launch()
```

Code after:
            history = self._tuples_to_messages(history)  # type: ignore
        else:
            history = copy.deepcopy(history)
        history.extend(message_dicts)  # type: ignore
        if self.type == "tuples":
            history = self._messages_to_tuples(history)  # type: ignore
        return history

    def _message_as_message_dict(
        self,
        message: MessageDict | Message | str | Component | MultimodalPostprocess | list,
        role: Literal["user", "assistant"],
    ) -> list[MessageDict]:
        """
        Converts a user message, example message, or response from the chat function to a
        list of MessageDict objects that can be appended to the chat history.
        """
        message_dicts = []
        if not isinstance(message, list):
            message = [message]
        for msg in message:
            if isinstance(msg, Message):
                message_dicts.append(msg.model_dump())
            elif isinstance(msg, ChatMessage):
                msg.role = role
                message_dicts.append(
                    dataclasses.asdict(msg, dict_factory=utils.dict_factory)
                )
            elif isinstance(msg, (str, Component)):
                message_dicts.append({"role": role, "content": msg})
            elif (
                isinstance(msg, dict) and "content" in msg
            ):  # in MessageDict format already
                msg["role"] = role
                message_dicts.append(msg)
            else:  # in MultimodalPostprocess format
                for x in msg.get("files", []):
                    if isinstance(x, dict):
                        x = x.get("path")
                    message_dicts.append({"role": role, "content": (x,)})
                if msg["text"] is None or not isinstance(msg["text"], str):
                    pass
                else:
                    message_dicts.append({"role": role, "content": msg["text"]})
        return message_dicts

    async def _submit_fn(
        self,
        message: str | MultimodalPostprocess,
        history: TupleFormat | list[MessageDict],
        *args,