async def tail_job_logs(self, job_id: str) -> AsyncIterator[dict]:
        """
        Follow job logs via websocket connection.

        Args:
            job_id: ID of the job to follow logs for

        Yields:
            Dict containing either job status updates or log messages
        """
        parsed_url = urlparse(self.url)
        ws_url = urlunparse(
            parsed_url._replace(scheme="wss" if parsed_url.scheme == "https" else "ws")
        )
        ws_url = f"{ws_url}/logs/follow/?job_id={job_id}&team_name={self.team}"

        async with websockets.connect(
            ws_url,
            additional_headers={"Authorization": f"token {self.token}"},
        ) as websocket:
            while True:
                try:
                    message = await websocket.recv()
                    data = json.loads(message)

                    # Yield the parsed message data
                    yield data

                except websockets.exceptions.ConnectionClosed:
                    break
                except Exception as e:  # noqa: BLE001
                    logger.error("Error receiving websocket message: %s", e)
                    break

        Follow job logs via websocket connection.

        Args:
            job_id: ID of the job to follow logs for

        Yields:
            Dict containing either job status updates or log messages
        
src/datachain/remote/studio.py