async def export_messages_to_csv(
        self,
        columns: Optional[list[str]] = None,
        filters: Optional[dict] = None,
        include_header: bool = True,
        handle_images: str = "metadata_only",  # Options: "full", "metadata_only", "exclude"
    ) -> tuple[str, IO]:
        """
        Creates a CSV file from the PostgreSQL data and returns the path to the temp file.

        Args:
            columns: List of columns to include in export
            filters: Filter criteria for messages
            include_header: Whether to include header row
            handle_images: How to handle image data in exports:
                - "full": Include complete image data (warning: may create large files)
                - "metadata_only": Replace image data with metadata only
                - "exclude": Remove image data completely
        """
        valid_columns = {
            "id",
            "conversation_id",
            "parent_id",
            "content",
            "metadata",
            "created_at",
            "has_image",  # New virtual column to indicate image presence
        }

        if not columns:
            columns = list(valid_columns - {"has_image"})
        elif invalid_cols := set(columns) - valid_columns:
            raise ValueError(f"Invalid columns: {invalid_cols}")

        # Add virtual column for image presence
        virtual_columns = []
        has_image_column = False

        if "has_image" in columns:
            virtual_columns.append(
                "(content->>'image_url' IS NOT NULL OR content->>'image_data' IS NOT NULL) as has_image"
            )
            columns.remove("has_image")
            has_image_column = True

        select_stmt = f"""
            SELECT
                id::text,
                conversation_id::text,
                parent_id::text,
                content::text,
                metadata::text,
                to_char(created_at, 'YYYY-MM-DD HH24:MI:SS') AS created_at
                {", " + ", ".join(virtual_columns) if virtual_columns else ""}
            FROM {self._get_table_name("messages")}
        """

        # Keep existing filter conditions setup
        conditions = []
        params: list[Any] = []
        param_index = 1

        if filters:
            for field, value in filters.items():
                if field not in valid_columns or field == "has_image":
                    continue

                if isinstance(value, dict):
                    for op, val in value.items():
                        if op == "$eq":
                            conditions.append(f"{field} = ${param_index}")
                            params.append(val)
                            param_index += 1
                        elif op == "$gt":
                            conditions.append(f"{field} > ${param_index}")
                            params.append(val)
                            param_index += 1
                        elif op == "$lt":
                            conditions.append(f"{field} < ${param_index}")
                            params.append(val)
                            param_index += 1
                else:
                    conditions.append(f"{field} = ${param_index}")
                    params.append(value)
                    param_index += 1

        # Special filter for has_image
        if filters and "has_image" in filters:
            if filters["has_image"]:
                conditions.append(
                    "(content->>'image_url' IS NOT NULL OR content->>'image_data' IS NOT NULL)"
                )

        if conditions:
            select_stmt = f"{select_stmt} WHERE {' AND '.join(conditions)}"

        select_stmt = f"{select_stmt} ORDER BY created_at DESC"

        temp_file = None
        try:
            temp_file = tempfile.NamedTemporaryFile(
                mode="w", delete=True, suffix=".csv"
            )
            writer = csv.writer(temp_file, quoting=csv.QUOTE_ALL)

            # Prepare export columns
            export_columns = list(columns)
            if has_image_column:
                export_columns.append("has_image")

            if include_header:
                writer.writerow(export_columns)

            async with self.connection_manager.pool.get_connection() as conn:  # type: ignore
                async with conn.transaction():
                    cursor = await conn.cursor(select_stmt, *params)

                    chunk_size = 1000
                    while True:
                        rows = await cursor.fetch(chunk_size)
                        if not rows:
                            break
                        for row in rows:
                            row_dict = {
                                "id": row[0],
                                "conversation_id": row[1],
                                "parent_id": row[2],
                                "content": row[3],
                                "metadata": row[4],
                                "created_at": row[5],
                            }

                            # Add virtual column if present
                            if has_image_column:
                                row_dict["has_image"] = (
                                    "true" if row[6] else "false"
                                )

                            # Process image data based on handle_images setting
                            if (
                                "content" in columns
                                and handle_images != "full"
                            ):
                                try:
                                    content_json = json.loads(
                                        row_dict["content"]
                                    )

                                    if (
                                        "image_data" in content_json
                                        and content_json["image_data"]
                                    ):
                                        media_type = content_json[
                                            "image_data"
                                        ].get("media_type", "image/jpeg")

                                        if handle_images == "metadata_only":
                                            content_json["image_data"] = {
                                                "media_type": media_type,
                                                "data": "[BASE64_DATA_EXCLUDED_FROM_EXPORT]",
                                            }
                                        elif handle_images == "exclude":
                                            content_json.pop(
                                                "image_data", None
                                            )

                                    row_dict["content"] = json.dumps(
                                        content_json
                                    )
                                except (json.JSONDecodeError, TypeError) as e:
                                    logger.warning(
                                        f"Error processing message content for export: {e}"
                                    )

                            writer.writerow(
                                [row_dict[col] for col in export_columns]
                            )

            temp_file.flush()
            return temp_file.name, temp_file

        except Exception as e:
            if temp_file:
                temp_file.close()
            raise HTTPException(
                status_code=500,
                detail=f"Failed to export data: {str(e)}",
            ) from e

        Creates a CSV file from the PostgreSQL data and returns the path to the temp file.

        Args:
            columns: List of columns to include in export
            filters: Filter criteria for messages
            include_header: Whether to include header row
            handle_images: How to handle image data in exports:
                - "full": Include complete image data (warning: may create large files)
                - "metadata_only": Replace image data with metadata only
                - "exclude": Remove image data completely
        
py/core/providers/database/conversations.py