# This file was auto-generated by Fern from our API Definition.

import contextlib
import typing
from json.decoder import JSONDecodeError
from logging import error, warning

from ..core.api_error import ApiError
from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ..core.http_response import AsyncHttpResponse, HttpResponse
from ..core.http_sse._api import EventSource
from ..core.jsonable_encoder import jsonable_encoder
from ..core.pydantic_utilities import parse_obj_as
from ..core.request_options import RequestOptions
from ..core.serialization import convert_and_respect_annotation_metadata
from ..errors.unprocessable_entity_error import UnprocessableEntityError
from ..types.delete_response import DeleteResponse
from ..types.event import Event
from ..types.http_validation_error import HttpValidationError
from ..types.migrate_tasks_response import MigrateTasksResponse
from ..types.presigned_url_request import PresignedUrlRequest
from ..types.presigned_url_response import PresignedUrlResponse
from ..types.system_folder_response import SystemFolderResponse
from ..types.system_folder_sync_complete_response import SystemFolderSyncCompleteResponse
from ..types.system_folder_type import SystemFolderType
from ..types.system_folder_type_response import SystemFolderTypeResponse
from ..types.task import Task
from ..types.task_message_content import TaskMessageContent
from ..types.task_relationships import TaskRelationships
from ..types.task_response import TaskResponse
from ..types.text_stream_part_wrapper import TextStreamPartWrapper

# this is used as the default value for optional parameters
OMIT = typing.cast(typing.Any, ...)


class RawTasksClient:
    def __init__(self, *, client_wrapper: SyncClientWrapper):
        self._client_wrapper = client_wrapper

    def list(
        self,
        *,
        agent_id: typing.Optional[str] = None,
        agent_name: typing.Optional[str] = None,
        limit: typing.Optional[int] = None,
        page_number: typing.Optional[int] = None,
        order_by: typing.Optional[str] = None,
        order_direction: typing.Optional[str] = None,
        relationships: typing.Optional[typing.Union[TaskRelationships, typing.Sequence[TaskRelationships]]] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[typing.List[TaskResponse]]:
        """
        List all tasks.

        Parameters
        ----------
        agent_id : typing.Optional[str]

        agent_name : typing.Optional[str]

        limit : typing.Optional[int]

        page_number : typing.Optional[int]

        order_by : typing.Optional[str]

        order_direction : typing.Optional[str]

        relationships : typing.Optional[typing.Union[TaskRelationships, typing.Sequence[TaskRelationships]]]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[typing.List[TaskResponse]]
            Successful Response
        """
        _response = self._client_wrapper.httpx_client.request(
            "tasks",
            method="GET",
            params={
                "agent_id": agent_id,
                "agent_name": agent_name,
                "limit": limit,
                "page_number": page_number,
                "order_by": order_by,
                "order_direction": order_direction,
                "relationships": relationships,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    typing.List[TaskResponse],
                    parse_obj_as(
                        type_=typing.List[TaskResponse],  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        HttpValidationError,
                        parse_obj_as(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def create(
        self,
        *,
        agent_id: typing.Optional[str] = OMIT,
        agent_name: typing.Optional[str] = OMIT,
        branch: typing.Optional[str] = OMIT,
        filesystem_id: typing.Optional[str] = OMIT,
        name: typing.Optional[str] = OMIT,
        params: typing.Optional[typing.Dict[str, typing.Any]] = OMIT,
        project_id: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[TaskResponse]:
        """
        Create a new task for an agent.

        Parameters
        ----------
        agent_id : typing.Optional[str]
            Agent ID (provide this OR agent_name)

        agent_name : typing.Optional[str]
            Agent name as 'namespace/name' (provide this OR agent_id)

        branch : typing.Optional[str]
            Target branch for version routing

        filesystem_id : typing.Optional[str]
            Existing filesystem ID

        name : typing.Optional[str]
            Task name

        params : typing.Optional[typing.Dict[str, typing.Any]]
            Task parameters

        project_id : typing.Optional[str]
            Project ID for new filesystem

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[TaskResponse]
            Successful Response
        """
        _response = self._client_wrapper.httpx_client.request(
            "tasks",
            method="POST",
            json={
                "agent_id": agent_id,
                "agent_name": agent_name,
                "branch": branch,
                "filesystem_id": filesystem_id,
                "name": name,
                "params": params,
                "project_id": project_id,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    TaskResponse,
                    parse_obj_as(
                        type_=TaskResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        HttpValidationError,
                        parse_obj_as(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def migrate(
        self,
        *,
        from_version_id: typing.Optional[str] = OMIT,
        task_ids: typing.Optional[typing.Sequence[str]] = OMIT,
        to_latest: typing.Optional[bool] = OMIT,
        to_version_id: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[MigrateTasksResponse]:
        """
        Migrate tasks between versions within the same branch. Supports two modes: bulk migration by source version (from_version_id), or migration of specific tasks (task_ids). Target can be explicit (to_version_id) or latest active version (to_latest).

        Parameters
        ----------
        from_version_id : typing.Optional[str]
            Migrate ALL RUNNING tasks from this version

        task_ids : typing.Optional[typing.Sequence[str]]
            OR migrate specific task IDs

        to_latest : typing.Optional[bool]
            OR migrate to ACTIVE/DEPLOYING version on branch

        to_version_id : typing.Optional[str]
            Explicit target version ID

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[MigrateTasksResponse]
            Successful Response
        """
        _response = self._client_wrapper.httpx_client.request(
            "tasks/migrate",
            method="POST",
            json={
                "from_version_id": from_version_id,
                "task_ids": task_ids,
                "to_latest": to_latest,
                "to_version_id": to_version_id,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    MigrateTasksResponse,
                    parse_obj_as(
                        type_=MigrateTasksResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        HttpValidationError,
                        parse_obj_as(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def retrieve_by_name(
        self,
        task_name: str,
        *,
        relationships: typing.Optional[typing.Union[TaskRelationships, typing.Sequence[TaskRelationships]]] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[TaskResponse]:
        """
        Get a task by its unique name.

        Parameters
        ----------
        task_name : str

        relationships : typing.Optional[typing.Union[TaskRelationships, typing.Sequence[TaskRelationships]]]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[TaskResponse]
            Successful Response
        """
        _response = self._client_wrapper.httpx_client.request(
            f"tasks/name/{jsonable_encoder(task_name)}",
            method="GET",
            params={
                "relationships": relationships,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    TaskResponse,
                    parse_obj_as(
                        type_=TaskResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        HttpValidationError,
                        parse_obj_as(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def update_by_name(
        self,
        task_name: str,
        *,
        task_metadata: typing.Optional[typing.Dict[str, typing.Any]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[Task]:
        """
        Update mutable fields for a task by its unique Name.

        Parameters
        ----------
        task_name : str

        task_metadata : typing.Optional[typing.Dict[str, typing.Any]]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[Task]
            Successful Response
        """
        _response = self._client_wrapper.httpx_client.request(
            f"tasks/name/{jsonable_encoder(task_name)}",
            method="PUT",
            json={
                "task_metadata": task_metadata,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    Task,
                    parse_obj_as(
                        type_=Task,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        HttpValidationError,
                        parse_obj_as(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def delete_by_name(
        self, task_name: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[DeleteResponse]:
        """
        Delete a task by its unique name.

        Parameters
        ----------
        task_name : str

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[DeleteResponse]
            Successful Response
        """
        _response = self._client_wrapper.httpx_client.request(
            f"tasks/name/{jsonable_encoder(task_name)}",
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DeleteResponse,
                    parse_obj_as(
                        type_=DeleteResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        HttpValidationError,
                        parse_obj_as(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    @contextlib.contextmanager
    def stream_by_name(
        self, task_name: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> typing.Iterator[HttpResponse[typing.Iterator[TextStreamPartWrapper]]]:
        """
        Stream events for a task by its unique name using Server-Sent Events (SSE).

            Supports automatic reconnection with Last-Event-ID header. When the client
            reconnects, it sends the Last-Event-ID header with the last received event ID,
            and the server resumes from that point.

            Returns TextStreamPart events (Vercel AI SDK compatible format).

        Parameters
        ----------
        task_name : str

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Yields
        ------
        typing.Iterator[HttpResponse[typing.Iterator[TextStreamPartWrapper]]]
            SSE stream of TextStreamPart events
        """
        with self._client_wrapper.httpx_client.stream(
            f"tasks/name/{jsonable_encoder(task_name)}/stream",
            method="GET",
            request_options=request_options,
        ) as _response:

            def _stream() -> HttpResponse[typing.Iterator[TextStreamPartWrapper]]:
                try:
                    if 200 <= _response.status_code < 300:

                        def _iter():
                            _event_source = EventSource(_response)
                            for _sse in _event_source.iter_sse():
                                if _sse.data == None:
                                    return
                                try:
                                    yield typing.cast(
                                        TextStreamPartWrapper,
                                        parse_obj_as(
                                            type_=TextStreamPartWrapper,  # type: ignore
                                            object_=_sse.json(),
                                        ),
                                    )
                                except JSONDecodeError as e:
                                    warning(f"Skipping SSE event with invalid JSON: {e}, sse: {_sse!r}")
                                except (TypeError, ValueError, KeyError, AttributeError) as e:
                                    warning(
                                        f"Skipping SSE event due to model construction error: {type(e).__name__}: {e}, sse: {_sse!r}"
                                    )
                                except Exception as e:
                                    error(
                                        f"Unexpected error processing SSE event: {type(e).__name__}: {e}, sse: {_sse!r}"
                                    )
                            return

                        return HttpResponse(response=_response, data=_iter())
                    _response.read()
                    if _response.status_code == 422:
                        raise UnprocessableEntityError(
                            headers=dict(_response.headers),
                            body=typing.cast(
                                HttpValidationError,
                                parse_obj_as(
                                    type_=HttpValidationError,  # type: ignore
                                    object_=_response.json(),
                                ),
                            ),
                        )
                    _response_json = _response.json()
                except JSONDecodeError:
                    raise ApiError(
                        status_code=_response.status_code, headers=dict(_response.headers), body=_response.text
                    )
                raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

            yield _stream()

    def retrieve(
        self,
        task_id: str,
        *,
        relationships: typing.Optional[typing.Union[TaskRelationships, typing.Sequence[TaskRelationships]]] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[TaskResponse]:
        """
        Get a task by its unique ID.

        Parameters
        ----------
        task_id : str

        relationships : typing.Optional[typing.Union[TaskRelationships, typing.Sequence[TaskRelationships]]]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[TaskResponse]
            Successful Response
        """
        _response = self._client_wrapper.httpx_client.request(
            f"tasks/{jsonable_encoder(task_id)}",
            method="GET",
            params={
                "relationships": relationships,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    TaskResponse,
                    parse_obj_as(
                        type_=TaskResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        HttpValidationError,
                        parse_obj_as(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def update(
        self,
        task_id: str,
        *,
        task_metadata: typing.Optional[typing.Dict[str, typing.Any]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[Task]:
        """
        Update mutable fields for a task by its unique ID.

        Parameters
        ----------
        task_id : str

        task_metadata : typing.Optional[typing.Dict[str, typing.Any]]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[Task]
            Successful Response
        """
        _response = self._client_wrapper.httpx_client.request(
            f"tasks/{jsonable_encoder(task_id)}",
            method="PUT",
            json={
                "task_metadata": task_metadata,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    Task,
                    parse_obj_as(
                        type_=Task,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        HttpValidationError,
                        parse_obj_as(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def delete(
        self, task_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[DeleteResponse]:
        """
        Delete a task by its unique ID.

        Parameters
        ----------
        task_id : str

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[DeleteResponse]
            Successful Response
        """
        _response = self._client_wrapper.httpx_client.request(
            f"tasks/{jsonable_encoder(task_id)}",
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DeleteResponse,
                    parse_obj_as(
                        type_=DeleteResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        HttpValidationError,
                        parse_obj_as(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def cancel(
        self, task_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[TaskResponse]:
        """
        Cancel a running task.

        Parameters
        ----------
        task_id : str

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[TaskResponse]
            Successful Response
        """
        _response = self._client_wrapper.httpx_client.request(
            f"tasks/{jsonable_encoder(task_id)}/cancel",
            method="POST",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    TaskResponse,
                    parse_obj_as(
                        type_=TaskResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        HttpValidationError,
                        parse_obj_as(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def send_event(
        self,
        task_id: str,
        *,
        content: typing.Optional[TaskMessageContent] = OMIT,
        persist_message: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[Event]:
        """
        Send an event to a running task.

        Parameters
        ----------
        task_id : str

        content : typing.Optional[TaskMessageContent]
            Event content

        persist_message : typing.Optional[bool]
            Whether to also create a message record for this event. Defaults to True.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[Event]
            Successful Response
        """
        _response = self._client_wrapper.httpx_client.request(
            f"tasks/{jsonable_encoder(task_id)}/events",
            method="POST",
            json={
                "content": convert_and_respect_annotation_metadata(
                    object_=content, annotation=typing.Optional[TaskMessageContent], direction="write"
                ),
                "persist_message": persist_message,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    Event,
                    parse_obj_as(
                        type_=Event,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        HttpValidationError,
                        parse_obj_as(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    @contextlib.contextmanager
    def stream(
        self, task_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> typing.Iterator[HttpResponse[typing.Iterator[TextStreamPartWrapper]]]:
        """
        Stream events for a task by its unique ID using Server-Sent Events (SSE).

            Supports automatic reconnection with Last-Event-ID header. When the client
            reconnects, it sends the Last-Event-ID header with the last received event ID,
            and the server resumes from that point.

            Returns TextStreamPart events (Vercel AI SDK compatible format).

        Parameters
        ----------
        task_id : str

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Yields
        ------
        typing.Iterator[HttpResponse[typing.Iterator[TextStreamPartWrapper]]]
            SSE stream of TextStreamPart events
        """
        with self._client_wrapper.httpx_client.stream(
            f"tasks/{jsonable_encoder(task_id)}/stream",
            method="GET",
            request_options=request_options,
        ) as _response:

            def _stream() -> HttpResponse[typing.Iterator[TextStreamPartWrapper]]:
                try:
                    if 200 <= _response.status_code < 300:

                        def _iter():
                            _event_source = EventSource(_response)
                            for _sse in _event_source.iter_sse():
                                if _sse.data == None:
                                    return
                                try:
                                    yield typing.cast(
                                        TextStreamPartWrapper,
                                        parse_obj_as(
                                            type_=TextStreamPartWrapper,  # type: ignore
                                            object_=_sse.json(),
                                        ),
                                    )
                                except JSONDecodeError as e:
                                    warning(f"Skipping SSE event with invalid JSON: {e}, sse: {_sse!r}")
                                except (TypeError, ValueError, KeyError, AttributeError) as e:
                                    warning(
                                        f"Skipping SSE event due to model construction error: {type(e).__name__}: {e}, sse: {_sse!r}"
                                    )
                                except Exception as e:
                                    error(
                                        f"Unexpected error processing SSE event: {type(e).__name__}: {e}, sse: {_sse!r}"
                                    )
                            return

                        return HttpResponse(response=_response, data=_iter())
                    _response.read()
                    if _response.status_code == 422:
                        raise UnprocessableEntityError(
                            headers=dict(_response.headers),
                            body=typing.cast(
                                HttpValidationError,
                                parse_obj_as(
                                    type_=HttpValidationError,  # type: ignore
                                    object_=_response.json(),
                                ),
                            ),
                        )
                    _response_json = _response.json()
                except JSONDecodeError:
                    raise ApiError(
                        status_code=_response.status_code, headers=dict(_response.headers), body=_response.text
                    )
                raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

            yield _stream()

    def list_system_folder_types(
        self, task_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[typing.List[SystemFolderTypeResponse]]:
        """
        Get all registered system folder types with their configurations for a task.

        Parameters
        ----------
        task_id : str

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[typing.List[SystemFolderTypeResponse]]
            Successful Response
        """
        _response = self._client_wrapper.httpx_client.request(
            f"tasks/{jsonable_encoder(task_id)}/system-folder-types",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    typing.List[SystemFolderTypeResponse],
                    parse_obj_as(
                        type_=typing.List[SystemFolderTypeResponse],  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        HttpValidationError,
                        parse_obj_as(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def get_system_folder(
        self, task_id: str, folder_type: SystemFolderType, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[typing.Optional[SystemFolderResponse]]:
        """
        Get a task's system folder record by type.

        Parameters
        ----------
        task_id : str

        folder_type : SystemFolderType

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[typing.Optional[SystemFolderResponse]]
            Successful Response
        """
        _response = self._client_wrapper.httpx_client.request(
            f"tasks/{jsonable_encoder(task_id)}/system-folders/{jsonable_encoder(folder_type)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if _response is None or not _response.text.strip():
                return HttpResponse(response=_response, data=None)
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    typing.Optional[SystemFolderResponse],
                    parse_obj_as(
                        type_=typing.Optional[SystemFolderResponse],  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        HttpValidationError,
                        parse_obj_as(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def get_system_folder_download_url(
        self,
        task_id: str,
        folder_type: SystemFolderType,
        *,
        request: typing.Optional[PresignedUrlRequest] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[typing.Optional[PresignedUrlResponse]]:
        """
        Get a presigned URL for direct download of a system folder archive from GCS.

        Parameters
        ----------
        task_id : str

        folder_type : SystemFolderType

        request : typing.Optional[PresignedUrlRequest]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[typing.Optional[PresignedUrlResponse]]
            Successful Response
        """
        _response = self._client_wrapper.httpx_client.request(
            f"tasks/{jsonable_encoder(task_id)}/system-folders/{jsonable_encoder(folder_type)}/download-url",
            method="POST",
            json=convert_and_respect_annotation_metadata(
                object_=request, annotation=typing.Optional[PresignedUrlRequest], direction="write"
            ),
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if _response is None or not _response.text.strip():
                return HttpResponse(response=_response, data=None)
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    typing.Optional[PresignedUrlResponse],
                    parse_obj_as(
                        type_=typing.Optional[PresignedUrlResponse],  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        HttpValidationError,
                        parse_obj_as(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def system_folder_sync_complete(
        self,
        task_id: str,
        folder_type: SystemFolderType,
        *,
        direction: str,
        status: str,
        sync_id: str,
        archive_checksum: typing.Optional[str] = OMIT,
        archive_size_bytes: typing.Optional[int] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[SystemFolderSyncCompleteResponse]:
        """
        Complete a system folder sync operation and update metadata.

        Parameters
        ----------
        task_id : str

        folder_type : SystemFolderType

        direction : str
            Sync direction: 'UP' or 'DOWN'.

        status : str
            Sync status: 'SUCCESS' or 'FAILED'.

        sync_id : str
            Unique ID for this sync operation (idempotency key).

        archive_checksum : typing.Optional[str]
            SHA256 checksum of the archive.

        archive_size_bytes : typing.Optional[int]
            Size of the archive in bytes.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[SystemFolderSyncCompleteResponse]
            Successful Response
        """
        _response = self._client_wrapper.httpx_client.request(
            f"tasks/{jsonable_encoder(task_id)}/system-folders/{jsonable_encoder(folder_type)}/sync-complete",
            method="POST",
            json={
                "archive_checksum": archive_checksum,
                "archive_size_bytes": archive_size_bytes,
                "direction": direction,
                "status": status,
                "sync_id": sync_id,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    SystemFolderSyncCompleteResponse,
                    parse_obj_as(
                        type_=SystemFolderSyncCompleteResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        HttpValidationError,
                        parse_obj_as(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def get_system_folder_upload_url(
        self,
        task_id: str,
        folder_type: SystemFolderType,
        *,
        request: typing.Optional[PresignedUrlRequest] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[PresignedUrlResponse]:
        """
        Get a presigned URL for direct upload of a system folder archive to GCS.

        Parameters
        ----------
        task_id : str

        folder_type : SystemFolderType

        request : typing.Optional[PresignedUrlRequest]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        HttpResponse[PresignedUrlResponse]
            Successful Response
        """
        _response = self._client_wrapper.httpx_client.request(
            f"tasks/{jsonable_encoder(task_id)}/system-folders/{jsonable_encoder(folder_type)}/upload-url",
            method="POST",
            json=convert_and_respect_annotation_metadata(
                object_=request, annotation=typing.Optional[PresignedUrlRequest], direction="write"
            ),
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    PresignedUrlResponse,
                    parse_obj_as(
                        type_=PresignedUrlResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        HttpValidationError,
                        parse_obj_as(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)


class AsyncRawTasksClient:
    def __init__(self, *, client_wrapper: AsyncClientWrapper):
        self._client_wrapper = client_wrapper

    async def list(
        self,
        *,
        agent_id: typing.Optional[str] = None,
        agent_name: typing.Optional[str] = None,
        limit: typing.Optional[int] = None,
        page_number: typing.Optional[int] = None,
        order_by: typing.Optional[str] = None,
        order_direction: typing.Optional[str] = None,
        relationships: typing.Optional[typing.Union[TaskRelationships, typing.Sequence[TaskRelationships]]] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[typing.List[TaskResponse]]:
        """
        List all tasks.

        Parameters
        ----------
        agent_id : typing.Optional[str]

        agent_name : typing.Optional[str]

        limit : typing.Optional[int]

        page_number : typing.Optional[int]

        order_by : typing.Optional[str]

        order_direction : typing.Optional[str]

        relationships : typing.Optional[typing.Union[TaskRelationships, typing.Sequence[TaskRelationships]]]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[typing.List[TaskResponse]]
            Successful Response
        """
        _response = await self._client_wrapper.httpx_client.request(
            "tasks",
            method="GET",
            params={
                "agent_id": agent_id,
                "agent_name": agent_name,
                "limit": limit,
                "page_number": page_number,
                "order_by": order_by,
                "order_direction": order_direction,
                "relationships": relationships,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    typing.List[TaskResponse],
                    parse_obj_as(
                        type_=typing.List[TaskResponse],  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        HttpValidationError,
                        parse_obj_as(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def create(
        self,
        *,
        agent_id: typing.Optional[str] = OMIT,
        agent_name: typing.Optional[str] = OMIT,
        branch: typing.Optional[str] = OMIT,
        filesystem_id: typing.Optional[str] = OMIT,
        name: typing.Optional[str] = OMIT,
        params: typing.Optional[typing.Dict[str, typing.Any]] = OMIT,
        project_id: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[TaskResponse]:
        """
        Create a new task for an agent.

        Parameters
        ----------
        agent_id : typing.Optional[str]
            Agent ID (provide this OR agent_name)

        agent_name : typing.Optional[str]
            Agent name as 'namespace/name' (provide this OR agent_id)

        branch : typing.Optional[str]
            Target branch for version routing

        filesystem_id : typing.Optional[str]
            Existing filesystem ID

        name : typing.Optional[str]
            Task name

        params : typing.Optional[typing.Dict[str, typing.Any]]
            Task parameters

        project_id : typing.Optional[str]
            Project ID for new filesystem

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[TaskResponse]
            Successful Response
        """
        _response = await self._client_wrapper.httpx_client.request(
            "tasks",
            method="POST",
            json={
                "agent_id": agent_id,
                "agent_name": agent_name,
                "branch": branch,
                "filesystem_id": filesystem_id,
                "name": name,
                "params": params,
                "project_id": project_id,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    TaskResponse,
                    parse_obj_as(
                        type_=TaskResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        HttpValidationError,
                        parse_obj_as(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def migrate(
        self,
        *,
        from_version_id: typing.Optional[str] = OMIT,
        task_ids: typing.Optional[typing.Sequence[str]] = OMIT,
        to_latest: typing.Optional[bool] = OMIT,
        to_version_id: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[MigrateTasksResponse]:
        """
        Migrate tasks between versions within the same branch. Supports two modes: bulk migration by source version (from_version_id), or migration of specific tasks (task_ids). Target can be explicit (to_version_id) or latest active version (to_latest).

        Parameters
        ----------
        from_version_id : typing.Optional[str]
            Migrate ALL RUNNING tasks from this version

        task_ids : typing.Optional[typing.Sequence[str]]
            OR migrate specific task IDs

        to_latest : typing.Optional[bool]
            OR migrate to ACTIVE/DEPLOYING version on branch

        to_version_id : typing.Optional[str]
            Explicit target version ID

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[MigrateTasksResponse]
            Successful Response
        """
        _response = await self._client_wrapper.httpx_client.request(
            "tasks/migrate",
            method="POST",
            json={
                "from_version_id": from_version_id,
                "task_ids": task_ids,
                "to_latest": to_latest,
                "to_version_id": to_version_id,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    MigrateTasksResponse,
                    parse_obj_as(
                        type_=MigrateTasksResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        HttpValidationError,
                        parse_obj_as(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def retrieve_by_name(
        self,
        task_name: str,
        *,
        relationships: typing.Optional[typing.Union[TaskRelationships, typing.Sequence[TaskRelationships]]] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[TaskResponse]:
        """
        Get a task by its unique name.

        Parameters
        ----------
        task_name : str

        relationships : typing.Optional[typing.Union[TaskRelationships, typing.Sequence[TaskRelationships]]]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[TaskResponse]
            Successful Response
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"tasks/name/{jsonable_encoder(task_name)}",
            method="GET",
            params={
                "relationships": relationships,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    TaskResponse,
                    parse_obj_as(
                        type_=TaskResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        HttpValidationError,
                        parse_obj_as(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def update_by_name(
        self,
        task_name: str,
        *,
        task_metadata: typing.Optional[typing.Dict[str, typing.Any]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[Task]:
        """
        Update mutable fields for a task by its unique Name.

        Parameters
        ----------
        task_name : str

        task_metadata : typing.Optional[typing.Dict[str, typing.Any]]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[Task]
            Successful Response
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"tasks/name/{jsonable_encoder(task_name)}",
            method="PUT",
            json={
                "task_metadata": task_metadata,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    Task,
                    parse_obj_as(
                        type_=Task,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        HttpValidationError,
                        parse_obj_as(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def delete_by_name(
        self, task_name: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[DeleteResponse]:
        """
        Delete a task by its unique name.

        Parameters
        ----------
        task_name : str

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[DeleteResponse]
            Successful Response
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"tasks/name/{jsonable_encoder(task_name)}",
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DeleteResponse,
                    parse_obj_as(
                        type_=DeleteResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        HttpValidationError,
                        parse_obj_as(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    @contextlib.asynccontextmanager
    async def stream_by_name(
        self, task_name: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[TextStreamPartWrapper]]]:
        """
        Stream events for a task by its unique name using Server-Sent Events (SSE).

            Supports automatic reconnection with Last-Event-ID header. When the client
            reconnects, it sends the Last-Event-ID header with the last received event ID,
            and the server resumes from that point.

            Returns TextStreamPart events (Vercel AI SDK compatible format).

        Parameters
        ----------
        task_name : str

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Yields
        ------
        typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[TextStreamPartWrapper]]]
            SSE stream of TextStreamPart events
        """
        async with self._client_wrapper.httpx_client.stream(
            f"tasks/name/{jsonable_encoder(task_name)}/stream",
            method="GET",
            request_options=request_options,
        ) as _response:

            async def _stream() -> AsyncHttpResponse[typing.AsyncIterator[TextStreamPartWrapper]]:
                try:
                    if 200 <= _response.status_code < 300:

                        async def _iter():
                            _event_source = EventSource(_response)
                            async for _sse in _event_source.aiter_sse():
                                if _sse.data == None:
                                    return
                                try:
                                    yield typing.cast(
                                        TextStreamPartWrapper,
                                        parse_obj_as(
                                            type_=TextStreamPartWrapper,  # type: ignore
                                            object_=_sse.json(),
                                        ),
                                    )
                                except JSONDecodeError as e:
                                    warning(f"Skipping SSE event with invalid JSON: {e}, sse: {_sse!r}")
                                except (TypeError, ValueError, KeyError, AttributeError) as e:
                                    warning(
                                        f"Skipping SSE event due to model construction error: {type(e).__name__}: {e}, sse: {_sse!r}"
                                    )
                                except Exception as e:
                                    error(
                                        f"Unexpected error processing SSE event: {type(e).__name__}: {e}, sse: {_sse!r}"
                                    )
                            return

                        return AsyncHttpResponse(response=_response, data=_iter())
                    await _response.aread()
                    if _response.status_code == 422:
                        raise UnprocessableEntityError(
                            headers=dict(_response.headers),
                            body=typing.cast(
                                HttpValidationError,
                                parse_obj_as(
                                    type_=HttpValidationError,  # type: ignore
                                    object_=_response.json(),
                                ),
                            ),
                        )
                    _response_json = _response.json()
                except JSONDecodeError:
                    raise ApiError(
                        status_code=_response.status_code, headers=dict(_response.headers), body=_response.text
                    )
                raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

            yield await _stream()

    async def retrieve(
        self,
        task_id: str,
        *,
        relationships: typing.Optional[typing.Union[TaskRelationships, typing.Sequence[TaskRelationships]]] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[TaskResponse]:
        """
        Get a task by its unique ID.

        Parameters
        ----------
        task_id : str

        relationships : typing.Optional[typing.Union[TaskRelationships, typing.Sequence[TaskRelationships]]]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[TaskResponse]
            Successful Response
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"tasks/{jsonable_encoder(task_id)}",
            method="GET",
            params={
                "relationships": relationships,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    TaskResponse,
                    parse_obj_as(
                        type_=TaskResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        HttpValidationError,
                        parse_obj_as(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def update(
        self,
        task_id: str,
        *,
        task_metadata: typing.Optional[typing.Dict[str, typing.Any]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[Task]:
        """
        Update mutable fields for a task by its unique ID.

        Parameters
        ----------
        task_id : str

        task_metadata : typing.Optional[typing.Dict[str, typing.Any]]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[Task]
            Successful Response
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"tasks/{jsonable_encoder(task_id)}",
            method="PUT",
            json={
                "task_metadata": task_metadata,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    Task,
                    parse_obj_as(
                        type_=Task,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        HttpValidationError,
                        parse_obj_as(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def delete(
        self, task_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[DeleteResponse]:
        """
        Delete a task by its unique ID.

        Parameters
        ----------
        task_id : str

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[DeleteResponse]
            Successful Response
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"tasks/{jsonable_encoder(task_id)}",
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DeleteResponse,
                    parse_obj_as(
                        type_=DeleteResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        HttpValidationError,
                        parse_obj_as(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def cancel(
        self, task_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[TaskResponse]:
        """
        Cancel a running task.

        Parameters
        ----------
        task_id : str

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[TaskResponse]
            Successful Response
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"tasks/{jsonable_encoder(task_id)}/cancel",
            method="POST",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    TaskResponse,
                    parse_obj_as(
                        type_=TaskResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        HttpValidationError,
                        parse_obj_as(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def send_event(
        self,
        task_id: str,
        *,
        content: typing.Optional[TaskMessageContent] = OMIT,
        persist_message: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[Event]:
        """
        Send an event to a running task.

        Parameters
        ----------
        task_id : str

        content : typing.Optional[TaskMessageContent]
            Event content

        persist_message : typing.Optional[bool]
            Whether to also create a message record for this event. Defaults to True.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[Event]
            Successful Response
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"tasks/{jsonable_encoder(task_id)}/events",
            method="POST",
            json={
                "content": convert_and_respect_annotation_metadata(
                    object_=content, annotation=typing.Optional[TaskMessageContent], direction="write"
                ),
                "persist_message": persist_message,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    Event,
                    parse_obj_as(
                        type_=Event,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        HttpValidationError,
                        parse_obj_as(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    @contextlib.asynccontextmanager
    async def stream(
        self, task_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[TextStreamPartWrapper]]]:
        """
        Stream events for a task by its unique ID using Server-Sent Events (SSE).

            Supports automatic reconnection with Last-Event-ID header. When the client
            reconnects, it sends the Last-Event-ID header with the last received event ID,
            and the server resumes from that point.

            Returns TextStreamPart events (Vercel AI SDK compatible format).

        Parameters
        ----------
        task_id : str

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Yields
        ------
        typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[TextStreamPartWrapper]]]
            SSE stream of TextStreamPart events
        """
        async with self._client_wrapper.httpx_client.stream(
            f"tasks/{jsonable_encoder(task_id)}/stream",
            method="GET",
            request_options=request_options,
        ) as _response:

            async def _stream() -> AsyncHttpResponse[typing.AsyncIterator[TextStreamPartWrapper]]:
                try:
                    if 200 <= _response.status_code < 300:

                        async def _iter():
                            _event_source = EventSource(_response)
                            async for _sse in _event_source.aiter_sse():
                                if _sse.data == None:
                                    return
                                try:
                                    yield typing.cast(
                                        TextStreamPartWrapper,
                                        parse_obj_as(
                                            type_=TextStreamPartWrapper,  # type: ignore
                                            object_=_sse.json(),
                                        ),
                                    )
                                except JSONDecodeError as e:
                                    warning(f"Skipping SSE event with invalid JSON: {e}, sse: {_sse!r}")
                                except (TypeError, ValueError, KeyError, AttributeError) as e:
                                    warning(
                                        f"Skipping SSE event due to model construction error: {type(e).__name__}: {e}, sse: {_sse!r}"
                                    )
                                except Exception as e:
                                    error(
                                        f"Unexpected error processing SSE event: {type(e).__name__}: {e}, sse: {_sse!r}"
                                    )
                            return

                        return AsyncHttpResponse(response=_response, data=_iter())
                    await _response.aread()
                    if _response.status_code == 422:
                        raise UnprocessableEntityError(
                            headers=dict(_response.headers),
                            body=typing.cast(
                                HttpValidationError,
                                parse_obj_as(
                                    type_=HttpValidationError,  # type: ignore
                                    object_=_response.json(),
                                ),
                            ),
                        )
                    _response_json = _response.json()
                except JSONDecodeError:
                    raise ApiError(
                        status_code=_response.status_code, headers=dict(_response.headers), body=_response.text
                    )
                raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

            yield await _stream()

    async def list_system_folder_types(
        self, task_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[typing.List[SystemFolderTypeResponse]]:
        """
        Get all registered system folder types with their configurations for a task.

        Parameters
        ----------
        task_id : str

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[typing.List[SystemFolderTypeResponse]]
            Successful Response
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"tasks/{jsonable_encoder(task_id)}/system-folder-types",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    typing.List[SystemFolderTypeResponse],
                    parse_obj_as(
                        type_=typing.List[SystemFolderTypeResponse],  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        HttpValidationError,
                        parse_obj_as(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def get_system_folder(
        self, task_id: str, folder_type: SystemFolderType, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[typing.Optional[SystemFolderResponse]]:
        """
        Get a task's system folder record by type.

        Parameters
        ----------
        task_id : str

        folder_type : SystemFolderType

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[typing.Optional[SystemFolderResponse]]
            Successful Response
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"tasks/{jsonable_encoder(task_id)}/system-folders/{jsonable_encoder(folder_type)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if _response is None or not _response.text.strip():
                return AsyncHttpResponse(response=_response, data=None)
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    typing.Optional[SystemFolderResponse],
                    parse_obj_as(
                        type_=typing.Optional[SystemFolderResponse],  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        HttpValidationError,
                        parse_obj_as(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def get_system_folder_download_url(
        self,
        task_id: str,
        folder_type: SystemFolderType,
        *,
        request: typing.Optional[PresignedUrlRequest] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[typing.Optional[PresignedUrlResponse]]:
        """
        Get a presigned URL for direct download of a system folder archive from GCS.

        Parameters
        ----------
        task_id : str

        folder_type : SystemFolderType

        request : typing.Optional[PresignedUrlRequest]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[typing.Optional[PresignedUrlResponse]]
            Successful Response
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"tasks/{jsonable_encoder(task_id)}/system-folders/{jsonable_encoder(folder_type)}/download-url",
            method="POST",
            json=convert_and_respect_annotation_metadata(
                object_=request, annotation=typing.Optional[PresignedUrlRequest], direction="write"
            ),
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if _response is None or not _response.text.strip():
                return AsyncHttpResponse(response=_response, data=None)
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    typing.Optional[PresignedUrlResponse],
                    parse_obj_as(
                        type_=typing.Optional[PresignedUrlResponse],  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        HttpValidationError,
                        parse_obj_as(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def system_folder_sync_complete(
        self,
        task_id: str,
        folder_type: SystemFolderType,
        *,
        direction: str,
        status: str,
        sync_id: str,
        archive_checksum: typing.Optional[str] = OMIT,
        archive_size_bytes: typing.Optional[int] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[SystemFolderSyncCompleteResponse]:
        """
        Complete a system folder sync operation and update metadata.

        Parameters
        ----------
        task_id : str

        folder_type : SystemFolderType

        direction : str
            Sync direction: 'UP' or 'DOWN'.

        status : str
            Sync status: 'SUCCESS' or 'FAILED'.

        sync_id : str
            Unique ID for this sync operation (idempotency key).

        archive_checksum : typing.Optional[str]
            SHA256 checksum of the archive.

        archive_size_bytes : typing.Optional[int]
            Size of the archive in bytes.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[SystemFolderSyncCompleteResponse]
            Successful Response
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"tasks/{jsonable_encoder(task_id)}/system-folders/{jsonable_encoder(folder_type)}/sync-complete",
            method="POST",
            json={
                "archive_checksum": archive_checksum,
                "archive_size_bytes": archive_size_bytes,
                "direction": direction,
                "status": status,
                "sync_id": sync_id,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    SystemFolderSyncCompleteResponse,
                    parse_obj_as(
                        type_=SystemFolderSyncCompleteResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        HttpValidationError,
                        parse_obj_as(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def get_system_folder_upload_url(
        self,
        task_id: str,
        folder_type: SystemFolderType,
        *,
        request: typing.Optional[PresignedUrlRequest] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[PresignedUrlResponse]:
        """
        Get a presigned URL for direct upload of a system folder archive to GCS.

        Parameters
        ----------
        task_id : str

        folder_type : SystemFolderType

        request : typing.Optional[PresignedUrlRequest]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncHttpResponse[PresignedUrlResponse]
            Successful Response
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"tasks/{jsonable_encoder(task_id)}/system-folders/{jsonable_encoder(folder_type)}/upload-url",
            method="POST",
            json=convert_and_respect_annotation_metadata(
                object_=request, annotation=typing.Optional[PresignedUrlRequest], direction="write"
            ),
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    PresignedUrlResponse,
                    parse_obj_as(
                        type_=PresignedUrlResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        HttpValidationError,
                        parse_obj_as(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
