# 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.pagination import AsyncPager, SyncPager
from ..core.request_options import RequestOptions
from ..core.serialization import convert_and_respect_annotation_metadata
from ..core.unchecked_base_model import construct_type
from .types.get_agents_response import GetAgentsResponse
from .types.get_history_agents_response import GetHistoryAgentsResponse
from .types.interrupt_agents_response import InterruptAgentsResponse
from .types.list_agents_request_state import ListAgentsRequestState
from .types.list_agents_response import ListAgentsResponse
from .types.list_agents_response_data_list_item import ListAgentsResponseDataListItem
from .types.speak_agents_request_priority import SpeakAgentsRequestPriority
from .types.speak_agents_response import SpeakAgentsResponse
from .types.start_agents_request_properties import StartAgentsRequestProperties
from .types.start_agents_response import StartAgentsResponse
from .types.update_agents_request_properties import UpdateAgentsRequestProperties
from .types.update_agents_response import UpdateAgentsResponse

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


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

    def start(
        self,
        appid: str,
        *,
        name: str,
        properties: StartAgentsRequestProperties,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[StartAgentsResponse]:
        """
        Create and start a Conversational AI agent instance.

        Parameters
        ----------
        appid : str
            The App ID of the project.

        name : str
            The unique identifier of the agent. The same identifier cannot be used repeatedly.

        properties : StartAgentsRequestProperties
            Configuration details of the agent.

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

        Returns
        -------
        HttpResponse[StartAgentsResponse]
            Request was successful. The response body contains the result of the request.
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/projects/{jsonable_encoder(appid)}/join",
            method="POST",
            json={
                "name": name,
                "properties": convert_and_respect_annotation_metadata(
                    object_=properties, annotation=StartAgentsRequestProperties, direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    StartAgentsResponse,
                    construct_type(
                        type_=StartAgentsResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _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 list(
        self,
        appid: str,
        *,
        channel: typing.Optional[str] = None,
        from_time: typing.Optional[float] = None,
        to_time: typing.Optional[float] = None,
        state: typing.Optional[ListAgentsRequestState] = None,
        limit: typing.Optional[int] = None,
        cursor: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> SyncPager[ListAgentsResponseDataListItem, ListAgentsResponse]:
        """
        Retrieve a list of agents that meet the specified conditions.

        Parameters
        ----------
        appid : str
            The App ID of the project.

        channel : typing.Optional[str]
            The channel to query for a list of agents.

        from_time : typing.Optional[float]
            The start timestamp (in seconds) for the query. Default is 2 hours ago.

        to_time : typing.Optional[float]
            The end timestamp (in seconds) for the query. Default is current time.

        state : typing.Optional[ListAgentsRequestState]
            The agent state to filter by. Only one state can be specified per query:
            - `IDLE` (0): Agent is idle.
            - `STARTING` (1): The agent is being started.
            - `RUNNING` (2): The agent is running.
            - `STOPPING` (3): The agent is stopping.
            - `STOPPED` (4): The agent has exited.
            - `RECOVERING` (5): The agent is recovering.
            - `FAILED` (6): The agent failed to execute.

        limit : typing.Optional[int]
            The maximum number of entries returned per page.

        cursor : typing.Optional[str]
            The paging cursor, indicating the starting position (`agent_id`) of the next page of results.

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

        Returns
        -------
        SyncPager[ListAgentsResponseDataListItem, ListAgentsResponse]
            Request was successful. The response body contains the result of the request.
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/projects/{jsonable_encoder(appid)}/agents",
            method="GET",
            params={
                "channel": channel,
                "from_time": from_time,
                "to_time": to_time,
                "state": state,
                "limit": limit,
                "cursor": cursor,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _parsed_response = typing.cast(
                    ListAgentsResponse,
                    construct_type(
                        type_=ListAgentsResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                _items = _parsed_response.data.list_ if _parsed_response.data is not None else []

                _has_next = False
                _get_next = None
                if _parsed_response.meta is not None:
                    _parsed_next = _parsed_response.meta.cursor
                    _has_next = _parsed_next is not None and _parsed_next != ""
                    _get_next = lambda: self.list(
                        appid,
                        channel=channel,
                        from_time=from_time,
                        to_time=to_time,
                        state=state,
                        limit=limit,
                        cursor=_parsed_next,
                        request_options=request_options,
                    )
                return SyncPager(has_next=_has_next, items=_items, get_next=_get_next, response=_parsed_response)
            _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(
        self, appid: str, agent_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[GetAgentsResponse]:
        """
        Get the current state information of the specified agent instance.

        Parameters
        ----------
        appid : str
            The App ID of the project.

        agent_id : str
            The agent instance ID you obtained after successfully calling `join` to start a conversational AI agent.

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

        Returns
        -------
        HttpResponse[GetAgentsResponse]
            Request was successful. The response body contains the result of the request.
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/projects/{jsonable_encoder(appid)}/agents/{jsonable_encoder(agent_id)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    GetAgentsResponse,
                    construct_type(
                        type_=GetAgentsResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _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_history(
        self, appid: str, agent_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[GetHistoryAgentsResponse]:
        """
        Get the history of the conversation between the user and the agent.

        Call this endpoint while the agent is running to retrieve the conversation history. You can set the maximum number of cached entries using the `llm.max_history` parameter when calling the start agent endpoint. The default value is `32`.

        Parameters
        ----------
        appid : str
            The App ID of the project.

        agent_id : str
            The agent instance ID you obtained after successfully calling `join` to start a conversational AI agent.

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

        Returns
        -------
        HttpResponse[GetHistoryAgentsResponse]
            Request was successful. The response body contains the result of the request.
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/projects/{jsonable_encoder(appid)}/agents/{jsonable_encoder(agent_id)}/history",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    GetHistoryAgentsResponse,
                    construct_type(
                        type_=GetHistoryAgentsResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _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 stop(
        self, appid: str, agent_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[None]:
        """
        Stop the specified conversational agent instance.

        Parameters
        ----------
        appid : str
            The App ID of the project.

        agent_id : str
            The agent instance ID you obtained after successfully calling `join` to start a conversational AI agent.

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

        Returns
        -------
        HttpResponse[None]
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/projects/{jsonable_encoder(appid)}/agents/{jsonable_encoder(agent_id)}/leave",
            method="POST",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return HttpResponse(response=_response, data=None)
            _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,
        appid: str,
        agent_id: str,
        *,
        properties: typing.Optional[UpdateAgentsRequestProperties] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[UpdateAgentsResponse]:
        """
        Adjust Conversation AI Engine parameters at runtime.

        Parameters
        ----------
        appid : str
            The App ID of the project.

        agent_id : str
            The agent instance ID you obtained after successfully calling `join` to start a conversational AI agent.

        properties : typing.Optional[UpdateAgentsRequestProperties]
            Configuration properties to update.

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

        Returns
        -------
        HttpResponse[UpdateAgentsResponse]
            Request was successful. The response body contains the result of the request.
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/projects/{jsonable_encoder(appid)}/agents/{jsonable_encoder(agent_id)}/update",
            method="POST",
            json={
                "properties": convert_and_respect_annotation_metadata(
                    object_=properties, annotation=UpdateAgentsRequestProperties, direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    UpdateAgentsResponse,
                    construct_type(
                        type_=UpdateAgentsResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _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 speak(
        self,
        appid: str,
        agent_id: str,
        *,
        text: str,
        priority: typing.Optional[SpeakAgentsRequestPriority] = OMIT,
        interruptable: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[SpeakAgentsResponse]:
        """
        Broadcast a custom message using the TTS module.

        During a conversation with an agent, call this endpoint to immediately broadcast a custom message using the TTS module. Upon receiving the request, the system interrupts the agent's speech and thought process to deliver the message. This broadcast can be interrupted by human voice.

        Note: The speak API is not supported when using `mllm` configuration.

        Parameters
        ----------
        appid : str
            The App ID of the project.

        agent_id : str
            The agent instance ID you obtained after successfully calling `join` to start a conversational AI agent.

        text : str
            The broadcast message text. The maximum length of the text content is 512 bytes.

        priority : typing.Optional[SpeakAgentsRequestPriority]
            Sets the priority of the message broadcast:
            - `INTERRUPT`: High priority. The agent immediately interrupts the current interaction to announce the message.
            - `APPEND`: Medium priority. The agent announces the message after the current interaction ends.
            - `IGNORE`: Low priority. If the agent is busy interacting, it ignores and discards the broadcast; the message is only announced if the agent is not interacting.

        interruptable : typing.Optional[bool]
            Whether to allow users to interrupt the agent's broadcast by speaking:
            - `true`: Allow
            - `false`: Don't allow

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

        Returns
        -------
        HttpResponse[SpeakAgentsResponse]
            Request was successful. The agent starts to broadcast the specified message.
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/projects/{jsonable_encoder(appid)}/agents/{jsonable_encoder(agent_id)}/speak",
            method="POST",
            json={
                "text": text,
                "priority": priority,
                "interruptable": interruptable,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    SpeakAgentsResponse,
                    construct_type(
                        type_=SpeakAgentsResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _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 interrupt(
        self, appid: str, agent_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[InterruptAgentsResponse]:
        """
        Interrupt the specified agent while speaking or thinking.

        Parameters
        ----------
        appid : str
            The App ID of the project.

        agent_id : str
            The agent instance ID you obtained after successfully calling `join` to start a conversational AI agent.

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

        Returns
        -------
        HttpResponse[InterruptAgentsResponse]
            Request was successful. The response body contains agent information and the agent stops talking and thinking immediately.
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/projects/{jsonable_encoder(appid)}/agents/{jsonable_encoder(agent_id)}/interrupt",
            method="POST",
            json={},
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    InterruptAgentsResponse,
                    construct_type(
                        type_=InterruptAgentsResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _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 AsyncRawAgentsClient:
    def __init__(self, *, client_wrapper: AsyncClientWrapper):
        self._client_wrapper = client_wrapper

    async def start(
        self,
        appid: str,
        *,
        name: str,
        properties: StartAgentsRequestProperties,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[StartAgentsResponse]:
        """
        Create and start a Conversational AI agent instance.

        Parameters
        ----------
        appid : str
            The App ID of the project.

        name : str
            The unique identifier of the agent. The same identifier cannot be used repeatedly.

        properties : StartAgentsRequestProperties
            Configuration details of the agent.

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

        Returns
        -------
        AsyncHttpResponse[StartAgentsResponse]
            Request was successful. The response body contains the result of the request.
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/projects/{jsonable_encoder(appid)}/join",
            method="POST",
            json={
                "name": name,
                "properties": convert_and_respect_annotation_metadata(
                    object_=properties, annotation=StartAgentsRequestProperties, direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    StartAgentsResponse,
                    construct_type(
                        type_=StartAgentsResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _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 list(
        self,
        appid: str,
        *,
        channel: typing.Optional[str] = None,
        from_time: typing.Optional[float] = None,
        to_time: typing.Optional[float] = None,
        state: typing.Optional[ListAgentsRequestState] = None,
        limit: typing.Optional[int] = None,
        cursor: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncPager[ListAgentsResponseDataListItem, ListAgentsResponse]:
        """
        Retrieve a list of agents that meet the specified conditions.

        Parameters
        ----------
        appid : str
            The App ID of the project.

        channel : typing.Optional[str]
            The channel to query for a list of agents.

        from_time : typing.Optional[float]
            The start timestamp (in seconds) for the query. Default is 2 hours ago.

        to_time : typing.Optional[float]
            The end timestamp (in seconds) for the query. Default is current time.

        state : typing.Optional[ListAgentsRequestState]
            The agent state to filter by. Only one state can be specified per query:
            - `IDLE` (0): Agent is idle.
            - `STARTING` (1): The agent is being started.
            - `RUNNING` (2): The agent is running.
            - `STOPPING` (3): The agent is stopping.
            - `STOPPED` (4): The agent has exited.
            - `RECOVERING` (5): The agent is recovering.
            - `FAILED` (6): The agent failed to execute.

        limit : typing.Optional[int]
            The maximum number of entries returned per page.

        cursor : typing.Optional[str]
            The paging cursor, indicating the starting position (`agent_id`) of the next page of results.

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

        Returns
        -------
        AsyncPager[ListAgentsResponseDataListItem, ListAgentsResponse]
            Request was successful. The response body contains the result of the request.
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/projects/{jsonable_encoder(appid)}/agents",
            method="GET",
            params={
                "channel": channel,
                "from_time": from_time,
                "to_time": to_time,
                "state": state,
                "limit": limit,
                "cursor": cursor,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _parsed_response = typing.cast(
                    ListAgentsResponse,
                    construct_type(
                        type_=ListAgentsResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                _items = _parsed_response.data.list_ if _parsed_response.data is not None else []

                _has_next = False
                _get_next = None
                if _parsed_response.meta is not None:
                    _parsed_next = _parsed_response.meta.cursor
                    _has_next = _parsed_next is not None and _parsed_next != ""

                    async def _get_next():
                        return await self.list(
                            appid,
                            channel=channel,
                            from_time=from_time,
                            to_time=to_time,
                            state=state,
                            limit=limit,
                            cursor=_parsed_next,
                            request_options=request_options,
                        )

                return AsyncPager(has_next=_has_next, items=_items, get_next=_get_next, response=_parsed_response)
            _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(
        self, appid: str, agent_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[GetAgentsResponse]:
        """
        Get the current state information of the specified agent instance.

        Parameters
        ----------
        appid : str
            The App ID of the project.

        agent_id : str
            The agent instance ID you obtained after successfully calling `join` to start a conversational AI agent.

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

        Returns
        -------
        AsyncHttpResponse[GetAgentsResponse]
            Request was successful. The response body contains the result of the request.
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/projects/{jsonable_encoder(appid)}/agents/{jsonable_encoder(agent_id)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    GetAgentsResponse,
                    construct_type(
                        type_=GetAgentsResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _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_history(
        self, appid: str, agent_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[GetHistoryAgentsResponse]:
        """
        Get the history of the conversation between the user and the agent.

        Call this endpoint while the agent is running to retrieve the conversation history. You can set the maximum number of cached entries using the `llm.max_history` parameter when calling the start agent endpoint. The default value is `32`.

        Parameters
        ----------
        appid : str
            The App ID of the project.

        agent_id : str
            The agent instance ID you obtained after successfully calling `join` to start a conversational AI agent.

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

        Returns
        -------
        AsyncHttpResponse[GetHistoryAgentsResponse]
            Request was successful. The response body contains the result of the request.
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/projects/{jsonable_encoder(appid)}/agents/{jsonable_encoder(agent_id)}/history",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    GetHistoryAgentsResponse,
                    construct_type(
                        type_=GetHistoryAgentsResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _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 stop(
        self, appid: str, agent_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[None]:
        """
        Stop the specified conversational agent instance.

        Parameters
        ----------
        appid : str
            The App ID of the project.

        agent_id : str
            The agent instance ID you obtained after successfully calling `join` to start a conversational AI agent.

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

        Returns
        -------
        AsyncHttpResponse[None]
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/projects/{jsonable_encoder(appid)}/agents/{jsonable_encoder(agent_id)}/leave",
            method="POST",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return AsyncHttpResponse(response=_response, data=None)
            _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,
        appid: str,
        agent_id: str,
        *,
        properties: typing.Optional[UpdateAgentsRequestProperties] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[UpdateAgentsResponse]:
        """
        Adjust Conversation AI Engine parameters at runtime.

        Parameters
        ----------
        appid : str
            The App ID of the project.

        agent_id : str
            The agent instance ID you obtained after successfully calling `join` to start a conversational AI agent.

        properties : typing.Optional[UpdateAgentsRequestProperties]
            Configuration properties to update.

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

        Returns
        -------
        AsyncHttpResponse[UpdateAgentsResponse]
            Request was successful. The response body contains the result of the request.
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/projects/{jsonable_encoder(appid)}/agents/{jsonable_encoder(agent_id)}/update",
            method="POST",
            json={
                "properties": convert_and_respect_annotation_metadata(
                    object_=properties, annotation=UpdateAgentsRequestProperties, direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    UpdateAgentsResponse,
                    construct_type(
                        type_=UpdateAgentsResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _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 speak(
        self,
        appid: str,
        agent_id: str,
        *,
        text: str,
        priority: typing.Optional[SpeakAgentsRequestPriority] = OMIT,
        interruptable: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[SpeakAgentsResponse]:
        """
        Broadcast a custom message using the TTS module.

        During a conversation with an agent, call this endpoint to immediately broadcast a custom message using the TTS module. Upon receiving the request, the system interrupts the agent's speech and thought process to deliver the message. This broadcast can be interrupted by human voice.

        Note: The speak API is not supported when using `mllm` configuration.

        Parameters
        ----------
        appid : str
            The App ID of the project.

        agent_id : str
            The agent instance ID you obtained after successfully calling `join` to start a conversational AI agent.

        text : str
            The broadcast message text. The maximum length of the text content is 512 bytes.

        priority : typing.Optional[SpeakAgentsRequestPriority]
            Sets the priority of the message broadcast:
            - `INTERRUPT`: High priority. The agent immediately interrupts the current interaction to announce the message.
            - `APPEND`: Medium priority. The agent announces the message after the current interaction ends.
            - `IGNORE`: Low priority. If the agent is busy interacting, it ignores and discards the broadcast; the message is only announced if the agent is not interacting.

        interruptable : typing.Optional[bool]
            Whether to allow users to interrupt the agent's broadcast by speaking:
            - `true`: Allow
            - `false`: Don't allow

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

        Returns
        -------
        AsyncHttpResponse[SpeakAgentsResponse]
            Request was successful. The agent starts to broadcast the specified message.
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/projects/{jsonable_encoder(appid)}/agents/{jsonable_encoder(agent_id)}/speak",
            method="POST",
            json={
                "text": text,
                "priority": priority,
                "interruptable": interruptable,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    SpeakAgentsResponse,
                    construct_type(
                        type_=SpeakAgentsResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _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 interrupt(
        self, appid: str, agent_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[InterruptAgentsResponse]:
        """
        Interrupt the specified agent while speaking or thinking.

        Parameters
        ----------
        appid : str
            The App ID of the project.

        agent_id : str
            The agent instance ID you obtained after successfully calling `join` to start a conversational AI agent.

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

        Returns
        -------
        AsyncHttpResponse[InterruptAgentsResponse]
            Request was successful. The response body contains agent information and the agent stops talking and thinking immediately.
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/projects/{jsonable_encoder(appid)}/agents/{jsonable_encoder(agent_id)}/interrupt",
            method="POST",
            json={},
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    InterruptAgentsResponse,
                    construct_type(
                        type_=InterruptAgentsResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _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)
