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

import typing
from json.decoder import JSONDecodeError

from ..core.api_error import ApiError
from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ..core.http_response import AsyncHttpResponse, HttpResponse
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.bad_request_error import BadRequestError
from ..errors.not_found_error import NotFoundError
from ..errors.unauthorized_error import UnauthorizedError
from ..types.agent_request import AgentRequest
from ..types.entity_ids_selector import EntityIdsSelector
from ..types.google_protobuf_any import GoogleProtobufAny
from ..types.principal import Principal
from ..types.relations import Relations
from ..types.task import Task
from ..types.task_entity import TaskEntity
from ..types.task_query_results import TaskQueryResults
from ..types.task_status import TaskStatus
from .types.task_query_status_filter import TaskQueryStatusFilter
from .types.task_query_update_time_range import TaskQueryUpdateTimeRange

# 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 create_task(
        self,
        *,
        task_id: typing.Optional[str] = OMIT,
        display_name: typing.Optional[str] = OMIT,
        description: typing.Optional[str] = OMIT,
        specification: typing.Optional[GoogleProtobufAny] = OMIT,
        author: typing.Optional[Principal] = OMIT,
        relations: typing.Optional[Relations] = OMIT,
        is_executed_elsewhere: typing.Optional[bool] = OMIT,
        initial_entities: typing.Optional[typing.Sequence[TaskEntity]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[Task]:
        """
        Submit a request to create a task and schedule it for delivery. Tasks, once delivered, will
        be asynchronously updated by their destined agent.

        Parameters
        ----------
        task_id : typing.Optional[str]
            If non-empty, will set the requested Task ID, otherwise will generate a new random
            GUID. Will reject if supplied Task ID does not match [A-Za-z0-9_-.]{5,36}.

        display_name : typing.Optional[str]
            Human readable display name for this Task, should be short (<100 chars).

        description : typing.Optional[str]
            Longer, free form human readable description of this Task.

        specification : typing.Optional[GoogleProtobufAny]
            Full set of task parameters.

        author : typing.Optional[Principal]

        relations : typing.Optional[Relations]
            Any relationships associated with this Task, such as a parent Task or an assignee
            this Task is designated to for execution.

        is_executed_elsewhere : typing.Optional[bool]
            If set, then the service will not trigger execution of this task on an agent. Useful
            for when ingesting tasks from an external system that is triggering execution of tasks
            on agents.

        initial_entities : typing.Optional[typing.Sequence[TaskEntity]]
            Indicates an initial set of entities that can be used to execute an entity aware
            task. For example, an entity Objective, an entity Keep In Zone, etc.

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

        Returns
        -------
        HttpResponse[Task]
            Task creation was successful
        """
        _response = self._client_wrapper.httpx_client.request(
            "api/v1/tasks",
            method="POST",
            json={
                "taskId": task_id,
                "displayName": display_name,
                "description": description,
                "specification": convert_and_respect_annotation_metadata(
                    object_=specification, annotation=GoogleProtobufAny, direction="write"
                ),
                "author": convert_and_respect_annotation_metadata(
                    object_=author, annotation=Principal, direction="write"
                ),
                "relations": convert_and_respect_annotation_metadata(
                    object_=relations, annotation=Relations, direction="write"
                ),
                "isExecutedElsewhere": is_executed_elsewhere,
                "initialEntities": convert_and_respect_annotation_metadata(
                    object_=initial_entities, annotation=typing.Sequence[TaskEntity], direction="write"
                ),
            },
            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 == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # 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_task(self, task_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> HttpResponse[Task]:
        """
        Parameters
        ----------
        task_id : str
            ID of task to return

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

        Returns
        -------
        HttpResponse[Task]
            Task retrieval was successful.
        """
        _response = self._client_wrapper.httpx_client.request(
            f"api/v1/tasks/{jsonable_encoder(task_id)}",
            method="GET",
            request_options=request_options,
        )
        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 == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # 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_task_status(
        self,
        task_id: str,
        *,
        status_version: typing.Optional[int] = OMIT,
        new_status: typing.Optional[TaskStatus] = OMIT,
        author: typing.Optional[Principal] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[Task]:
        """
        Update the status of a task.

        Parameters
        ----------
        task_id : str
            ID of task to update status of

        status_version : typing.Optional[int]
            The status version of the task to update. This version number increments to indicate the task's
            current stage in its status lifecycle. Specifically, whenever a task's status updates, the status
            version increments by one. Any status updates received with a lower status version number than what
            is known are considered stale and ignored.

        new_status : typing.Optional[TaskStatus]
            The new status of the task.

        author : typing.Optional[Principal]

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

        Returns
        -------
        HttpResponse[Task]
            Task status update was successful
        """
        _response = self._client_wrapper.httpx_client.request(
            f"api/v1/tasks/{jsonable_encoder(task_id)}/status",
            method="PUT",
            json={
                "statusVersion": status_version,
                "newStatus": convert_and_respect_annotation_metadata(
                    object_=new_status, annotation=TaskStatus, direction="write"
                ),
                "author": convert_and_respect_annotation_metadata(
                    object_=author, annotation=Principal, direction="write"
                ),
            },
            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 == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # 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 query_tasks(
        self,
        *,
        page_token: typing.Optional[str] = OMIT,
        parent_task_id: typing.Optional[str] = OMIT,
        status_filter: typing.Optional[TaskQueryStatusFilter] = OMIT,
        update_time_range: typing.Optional[TaskQueryUpdateTimeRange] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[TaskQueryResults]:
        """
        Query for tasks by a specified search criteria.

        Parameters
        ----------
        page_token : typing.Optional[str]
            If set, returns results starting from the given pageToken.

        parent_task_id : typing.Optional[str]
            If present matches Tasks with this parent Task ID.
            Note: this is mutually exclusive with all other query parameters, i.e., either provide parent Task ID, or
            any of the remaining parameters, but not both.

        status_filter : typing.Optional[TaskQueryStatusFilter]

        update_time_range : typing.Optional[TaskQueryUpdateTimeRange]
            If provided, only provides Tasks updated within the time range.

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

        Returns
        -------
        HttpResponse[TaskQueryResults]
            Task query was successful
        """
        _response = self._client_wrapper.httpx_client.request(
            "api/v1/tasks/query",
            method="POST",
            json={
                "pageToken": page_token,
                "parentTaskId": parent_task_id,
                "statusFilter": convert_and_respect_annotation_metadata(
                    object_=status_filter, annotation=TaskQueryStatusFilter, direction="write"
                ),
                "updateTimeRange": convert_and_respect_annotation_metadata(
                    object_=update_time_range, annotation=TaskQueryUpdateTimeRange, direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    TaskQueryResults,
                    parse_obj_as(
                        type_=TaskQueryResults,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # 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 listen_as_agent(
        self,
        *,
        agent_selector: typing.Optional[EntityIdsSelector] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[AgentRequest]:
        """
        This is a long polling API that will block until a new task is ready for delivery. If no new task is
        available then the server will hold on to your request for up to 5 minutes, after that 5 minute timeout
        period you will be expected to reinitiate a new request.

        Parameters
        ----------
        agent_selector : typing.Optional[EntityIdsSelector]
            Selector criteria to determine which Agent Tasks the agent receives

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

        Returns
        -------
        HttpResponse[AgentRequest]
            Requests for the agent to comply with.
        """
        _response = self._client_wrapper.httpx_client.request(
            "api/v1/agent/listen",
            method="POST",
            json={
                "agentSelector": convert_and_respect_annotation_metadata(
                    object_=agent_selector, annotation=EntityIdsSelector, direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    AgentRequest,
                    parse_obj_as(
                        type_=AgentRequest,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # 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 create_task(
        self,
        *,
        task_id: typing.Optional[str] = OMIT,
        display_name: typing.Optional[str] = OMIT,
        description: typing.Optional[str] = OMIT,
        specification: typing.Optional[GoogleProtobufAny] = OMIT,
        author: typing.Optional[Principal] = OMIT,
        relations: typing.Optional[Relations] = OMIT,
        is_executed_elsewhere: typing.Optional[bool] = OMIT,
        initial_entities: typing.Optional[typing.Sequence[TaskEntity]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[Task]:
        """
        Submit a request to create a task and schedule it for delivery. Tasks, once delivered, will
        be asynchronously updated by their destined agent.

        Parameters
        ----------
        task_id : typing.Optional[str]
            If non-empty, will set the requested Task ID, otherwise will generate a new random
            GUID. Will reject if supplied Task ID does not match [A-Za-z0-9_-.]{5,36}.

        display_name : typing.Optional[str]
            Human readable display name for this Task, should be short (<100 chars).

        description : typing.Optional[str]
            Longer, free form human readable description of this Task.

        specification : typing.Optional[GoogleProtobufAny]
            Full set of task parameters.

        author : typing.Optional[Principal]

        relations : typing.Optional[Relations]
            Any relationships associated with this Task, such as a parent Task or an assignee
            this Task is designated to for execution.

        is_executed_elsewhere : typing.Optional[bool]
            If set, then the service will not trigger execution of this task on an agent. Useful
            for when ingesting tasks from an external system that is triggering execution of tasks
            on agents.

        initial_entities : typing.Optional[typing.Sequence[TaskEntity]]
            Indicates an initial set of entities that can be used to execute an entity aware
            task. For example, an entity Objective, an entity Keep In Zone, etc.

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

        Returns
        -------
        AsyncHttpResponse[Task]
            Task creation was successful
        """
        _response = await self._client_wrapper.httpx_client.request(
            "api/v1/tasks",
            method="POST",
            json={
                "taskId": task_id,
                "displayName": display_name,
                "description": description,
                "specification": convert_and_respect_annotation_metadata(
                    object_=specification, annotation=GoogleProtobufAny, direction="write"
                ),
                "author": convert_and_respect_annotation_metadata(
                    object_=author, annotation=Principal, direction="write"
                ),
                "relations": convert_and_respect_annotation_metadata(
                    object_=relations, annotation=Relations, direction="write"
                ),
                "isExecutedElsewhere": is_executed_elsewhere,
                "initialEntities": convert_and_respect_annotation_metadata(
                    object_=initial_entities, annotation=typing.Sequence[TaskEntity], direction="write"
                ),
            },
            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 == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # 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_task(
        self, task_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[Task]:
        """
        Parameters
        ----------
        task_id : str
            ID of task to return

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

        Returns
        -------
        AsyncHttpResponse[Task]
            Task retrieval was successful.
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"api/v1/tasks/{jsonable_encoder(task_id)}",
            method="GET",
            request_options=request_options,
        )
        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 == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # 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_task_status(
        self,
        task_id: str,
        *,
        status_version: typing.Optional[int] = OMIT,
        new_status: typing.Optional[TaskStatus] = OMIT,
        author: typing.Optional[Principal] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[Task]:
        """
        Update the status of a task.

        Parameters
        ----------
        task_id : str
            ID of task to update status of

        status_version : typing.Optional[int]
            The status version of the task to update. This version number increments to indicate the task's
            current stage in its status lifecycle. Specifically, whenever a task's status updates, the status
            version increments by one. Any status updates received with a lower status version number than what
            is known are considered stale and ignored.

        new_status : typing.Optional[TaskStatus]
            The new status of the task.

        author : typing.Optional[Principal]

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

        Returns
        -------
        AsyncHttpResponse[Task]
            Task status update was successful
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"api/v1/tasks/{jsonable_encoder(task_id)}/status",
            method="PUT",
            json={
                "statusVersion": status_version,
                "newStatus": convert_and_respect_annotation_metadata(
                    object_=new_status, annotation=TaskStatus, direction="write"
                ),
                "author": convert_and_respect_annotation_metadata(
                    object_=author, annotation=Principal, direction="write"
                ),
            },
            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 == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # 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 query_tasks(
        self,
        *,
        page_token: typing.Optional[str] = OMIT,
        parent_task_id: typing.Optional[str] = OMIT,
        status_filter: typing.Optional[TaskQueryStatusFilter] = OMIT,
        update_time_range: typing.Optional[TaskQueryUpdateTimeRange] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[TaskQueryResults]:
        """
        Query for tasks by a specified search criteria.

        Parameters
        ----------
        page_token : typing.Optional[str]
            If set, returns results starting from the given pageToken.

        parent_task_id : typing.Optional[str]
            If present matches Tasks with this parent Task ID.
            Note: this is mutually exclusive with all other query parameters, i.e., either provide parent Task ID, or
            any of the remaining parameters, but not both.

        status_filter : typing.Optional[TaskQueryStatusFilter]

        update_time_range : typing.Optional[TaskQueryUpdateTimeRange]
            If provided, only provides Tasks updated within the time range.

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

        Returns
        -------
        AsyncHttpResponse[TaskQueryResults]
            Task query was successful
        """
        _response = await self._client_wrapper.httpx_client.request(
            "api/v1/tasks/query",
            method="POST",
            json={
                "pageToken": page_token,
                "parentTaskId": parent_task_id,
                "statusFilter": convert_and_respect_annotation_metadata(
                    object_=status_filter, annotation=TaskQueryStatusFilter, direction="write"
                ),
                "updateTimeRange": convert_and_respect_annotation_metadata(
                    object_=update_time_range, annotation=TaskQueryUpdateTimeRange, direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    TaskQueryResults,
                    parse_obj_as(
                        type_=TaskQueryResults,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # 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 listen_as_agent(
        self,
        *,
        agent_selector: typing.Optional[EntityIdsSelector] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[AgentRequest]:
        """
        This is a long polling API that will block until a new task is ready for delivery. If no new task is
        available then the server will hold on to your request for up to 5 minutes, after that 5 minute timeout
        period you will be expected to reinitiate a new request.

        Parameters
        ----------
        agent_selector : typing.Optional[EntityIdsSelector]
            Selector criteria to determine which Agent Tasks the agent receives

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

        Returns
        -------
        AsyncHttpResponse[AgentRequest]
            Requests for the agent to comply with.
        """
        _response = await self._client_wrapper.httpx_client.request(
            "api/v1/agent/listen",
            method="POST",
            json={
                "agentSelector": convert_and_respect_annotation_metadata(
                    object_=agent_selector, annotation=EntityIdsSelector, direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    AgentRequest,
                    parse_obj_as(
                        type_=AgentRequest,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # 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)
