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

import typing
from json.decoder import JSONDecodeError

from ..core.api_error import ApiError as core_api_error_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.internal_server_error import InternalServerError
from ..errors.not_found_error import NotFoundError
from ..types.add_thread_messages_response import AddThreadMessagesResponse
from ..types.api_error import ApiError as types_api_error_ApiError
from ..types.message import Message
from ..types.message_list_response import MessageListResponse
from ..types.role_type import RoleType
from ..types.success_response import SuccessResponse
from ..types.thread import Thread
from ..types.thread_context_response import ThreadContextResponse
from ..types.thread_list_response import ThreadListResponse

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


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

    def list_all(
        self,
        *,
        page_number: typing.Optional[int] = None,
        page_size: typing.Optional[int] = None,
        order_by: typing.Optional[str] = None,
        asc: typing.Optional[bool] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[ThreadListResponse]:
        """
        Returns all threads.

        Parameters
        ----------
        page_number : typing.Optional[int]
            Page number for pagination, starting from 1

        page_size : typing.Optional[int]
            Number of threads to retrieve per page.

        order_by : typing.Optional[str]
            Field to order the results by: created_at, updated_at, user_id, thread_id.

        asc : typing.Optional[bool]
            Order direction: true for ascending, false for descending.

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

        Returns
        -------
        HttpResponse[ThreadListResponse]
            List of threads
        """
        _response = self._client_wrapper.httpx_client.request(
            "threads",
            method="GET",
            params={
                "page_number": page_number,
                "page_size": page_size,
                "order_by": order_by,
                "asc": asc,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    ThreadListResponse,
                    parse_obj_as(
                        type_=ThreadListResponse,  # 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(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(
                status_code=_response.status_code, headers=dict(_response.headers), body=_response.text
            )
        raise core_api_error_ApiError(
            status_code=_response.status_code, headers=dict(_response.headers), body=_response_json
        )

    def create(
        self, *, thread_id: str, user_id: str, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[Thread]:
        """
        Start a new thread.

        Parameters
        ----------
        thread_id : str
            The unique identifier of the thread.

        user_id : str
            The unique identifier of the user associated with the thread

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

        Returns
        -------
        HttpResponse[Thread]
            The thread object.
        """
        _response = self._client_wrapper.httpx_client.request(
            "threads",
            method="POST",
            json={
                "thread_id": thread_id,
                "user_id": user_id,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    Thread,
                    parse_obj_as(
                        type_=Thread,  # 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(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(
                status_code=_response.status_code, headers=dict(_response.headers), body=_response.text
            )
        raise core_api_error_ApiError(
            status_code=_response.status_code, headers=dict(_response.headers), body=_response_json
        )

    def delete(
        self, thread_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[SuccessResponse]:
        """
        Deletes a thread.

        Parameters
        ----------
        thread_id : str
            The ID of the thread for which memory should be deleted.

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

        Returns
        -------
        HttpResponse[SuccessResponse]
            OK
        """
        _response = self._client_wrapper.httpx_client.request(
            f"threads/{jsonable_encoder(thread_id)}",
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    SuccessResponse,
                    parse_obj_as(
                        type_=SuccessResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(
                status_code=_response.status_code, headers=dict(_response.headers), body=_response.text
            )
        raise core_api_error_ApiError(
            status_code=_response.status_code, headers=dict(_response.headers), body=_response_json
        )

    def get_user_context(
        self,
        thread_id: str,
        *,
        lastn: typing.Optional[int] = None,
        min_rating: typing.Optional[float] = None,
        fast: typing.Optional[bool] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[ThreadContextResponse]:
        """
        Returns most relevant context for a given thread.

        Parameters
        ----------
        thread_id : str
            The ID of the thread for which to retrieve context.

        lastn : typing.Optional[int]
            The number of most recent memory entries to retrieve.

        min_rating : typing.Optional[float]
            The minimum rating by which to filter relevant facts.

        fast : typing.Optional[bool]
            If true, bypasses context summarization and returns raw search results.

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

        Returns
        -------
        HttpResponse[ThreadContextResponse]
            OK
        """
        _response = self._client_wrapper.httpx_client.request(
            f"threads/{jsonable_encoder(thread_id)}/context",
            method="GET",
            params={
                "lastn": lastn,
                "minRating": min_rating,
                "fast": fast,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    ThreadContextResponse,
                    parse_obj_as(
                        type_=ThreadContextResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(
                status_code=_response.status_code, headers=dict(_response.headers), body=_response.text
            )
        raise core_api_error_ApiError(
            status_code=_response.status_code, headers=dict(_response.headers), body=_response_json
        )

    def get(
        self,
        thread_id: str,
        *,
        limit: typing.Optional[int] = None,
        cursor: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[MessageListResponse]:
        """
        Returns messages for a thread.

        Parameters
        ----------
        thread_id : str
            Thread ID

        limit : typing.Optional[int]
            Limit the number of results returned

        cursor : typing.Optional[int]
            Cursor for pagination

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

        Returns
        -------
        HttpResponse[MessageListResponse]
            OK
        """
        _response = self._client_wrapper.httpx_client.request(
            f"threads/{jsonable_encoder(thread_id)}/messages",
            method="GET",
            params={
                "limit": limit,
                "cursor": cursor,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    MessageListResponse,
                    parse_obj_as(
                        type_=MessageListResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(
                status_code=_response.status_code, headers=dict(_response.headers), body=_response.text
            )
        raise core_api_error_ApiError(
            status_code=_response.status_code, headers=dict(_response.headers), body=_response_json
        )

    def add_messages(
        self,
        thread_id: str,
        *,
        messages: typing.Sequence[Message],
        ignore_roles: typing.Optional[typing.Sequence[RoleType]] = OMIT,
        return_context: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[AddThreadMessagesResponse]:
        """
        Add messages to a thread.

        Parameters
        ----------
        thread_id : str
            The ID of the thread to which messages should be added.

        messages : typing.Sequence[Message]
            A list of message objects, where each message contains a role and content.

        ignore_roles : typing.Optional[typing.Sequence[RoleType]]
            Optional list of role types to ignore when adding messages to graph memory.
            The message itself will still be added, retained and used as context for messages
            that are added to a user's graph.

        return_context : typing.Optional[bool]
            Optionally return memory context relevant to the most recent messages.

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

        Returns
        -------
        HttpResponse[AddThreadMessagesResponse]
            An object, optionally containing user context retrieved for the last thread message
        """
        _response = self._client_wrapper.httpx_client.request(
            f"threads/{jsonable_encoder(thread_id)}/messages",
            method="POST",
            json={
                "ignore_roles": ignore_roles,
                "messages": convert_and_respect_annotation_metadata(
                    object_=messages, annotation=typing.Sequence[Message], direction="write"
                ),
                "return_context": return_context,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    AddThreadMessagesResponse,
                    parse_obj_as(
                        type_=AddThreadMessagesResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(
                status_code=_response.status_code, headers=dict(_response.headers), body=_response.text
            )
        raise core_api_error_ApiError(
            status_code=_response.status_code, headers=dict(_response.headers), body=_response_json
        )


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

    async def list_all(
        self,
        *,
        page_number: typing.Optional[int] = None,
        page_size: typing.Optional[int] = None,
        order_by: typing.Optional[str] = None,
        asc: typing.Optional[bool] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[ThreadListResponse]:
        """
        Returns all threads.

        Parameters
        ----------
        page_number : typing.Optional[int]
            Page number for pagination, starting from 1

        page_size : typing.Optional[int]
            Number of threads to retrieve per page.

        order_by : typing.Optional[str]
            Field to order the results by: created_at, updated_at, user_id, thread_id.

        asc : typing.Optional[bool]
            Order direction: true for ascending, false for descending.

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

        Returns
        -------
        AsyncHttpResponse[ThreadListResponse]
            List of threads
        """
        _response = await self._client_wrapper.httpx_client.request(
            "threads",
            method="GET",
            params={
                "page_number": page_number,
                "page_size": page_size,
                "order_by": order_by,
                "asc": asc,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    ThreadListResponse,
                    parse_obj_as(
                        type_=ThreadListResponse,  # 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(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(
                status_code=_response.status_code, headers=dict(_response.headers), body=_response.text
            )
        raise core_api_error_ApiError(
            status_code=_response.status_code, headers=dict(_response.headers), body=_response_json
        )

    async def create(
        self, *, thread_id: str, user_id: str, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[Thread]:
        """
        Start a new thread.

        Parameters
        ----------
        thread_id : str
            The unique identifier of the thread.

        user_id : str
            The unique identifier of the user associated with the thread

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

        Returns
        -------
        AsyncHttpResponse[Thread]
            The thread object.
        """
        _response = await self._client_wrapper.httpx_client.request(
            "threads",
            method="POST",
            json={
                "thread_id": thread_id,
                "user_id": user_id,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    Thread,
                    parse_obj_as(
                        type_=Thread,  # 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(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(
                status_code=_response.status_code, headers=dict(_response.headers), body=_response.text
            )
        raise core_api_error_ApiError(
            status_code=_response.status_code, headers=dict(_response.headers), body=_response_json
        )

    async def delete(
        self, thread_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[SuccessResponse]:
        """
        Deletes a thread.

        Parameters
        ----------
        thread_id : str
            The ID of the thread for which memory should be deleted.

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

        Returns
        -------
        AsyncHttpResponse[SuccessResponse]
            OK
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"threads/{jsonable_encoder(thread_id)}",
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    SuccessResponse,
                    parse_obj_as(
                        type_=SuccessResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(
                status_code=_response.status_code, headers=dict(_response.headers), body=_response.text
            )
        raise core_api_error_ApiError(
            status_code=_response.status_code, headers=dict(_response.headers), body=_response_json
        )

    async def get_user_context(
        self,
        thread_id: str,
        *,
        lastn: typing.Optional[int] = None,
        min_rating: typing.Optional[float] = None,
        fast: typing.Optional[bool] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[ThreadContextResponse]:
        """
        Returns most relevant context for a given thread.

        Parameters
        ----------
        thread_id : str
            The ID of the thread for which to retrieve context.

        lastn : typing.Optional[int]
            The number of most recent memory entries to retrieve.

        min_rating : typing.Optional[float]
            The minimum rating by which to filter relevant facts.

        fast : typing.Optional[bool]
            If true, bypasses context summarization and returns raw search results.

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

        Returns
        -------
        AsyncHttpResponse[ThreadContextResponse]
            OK
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"threads/{jsonable_encoder(thread_id)}/context",
            method="GET",
            params={
                "lastn": lastn,
                "minRating": min_rating,
                "fast": fast,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    ThreadContextResponse,
                    parse_obj_as(
                        type_=ThreadContextResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(
                status_code=_response.status_code, headers=dict(_response.headers), body=_response.text
            )
        raise core_api_error_ApiError(
            status_code=_response.status_code, headers=dict(_response.headers), body=_response_json
        )

    async def get(
        self,
        thread_id: str,
        *,
        limit: typing.Optional[int] = None,
        cursor: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[MessageListResponse]:
        """
        Returns messages for a thread.

        Parameters
        ----------
        thread_id : str
            Thread ID

        limit : typing.Optional[int]
            Limit the number of results returned

        cursor : typing.Optional[int]
            Cursor for pagination

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

        Returns
        -------
        AsyncHttpResponse[MessageListResponse]
            OK
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"threads/{jsonable_encoder(thread_id)}/messages",
            method="GET",
            params={
                "limit": limit,
                "cursor": cursor,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    MessageListResponse,
                    parse_obj_as(
                        type_=MessageListResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(
                status_code=_response.status_code, headers=dict(_response.headers), body=_response.text
            )
        raise core_api_error_ApiError(
            status_code=_response.status_code, headers=dict(_response.headers), body=_response_json
        )

    async def add_messages(
        self,
        thread_id: str,
        *,
        messages: typing.Sequence[Message],
        ignore_roles: typing.Optional[typing.Sequence[RoleType]] = OMIT,
        return_context: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[AddThreadMessagesResponse]:
        """
        Add messages to a thread.

        Parameters
        ----------
        thread_id : str
            The ID of the thread to which messages should be added.

        messages : typing.Sequence[Message]
            A list of message objects, where each message contains a role and content.

        ignore_roles : typing.Optional[typing.Sequence[RoleType]]
            Optional list of role types to ignore when adding messages to graph memory.
            The message itself will still be added, retained and used as context for messages
            that are added to a user's graph.

        return_context : typing.Optional[bool]
            Optionally return memory context relevant to the most recent messages.

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

        Returns
        -------
        AsyncHttpResponse[AddThreadMessagesResponse]
            An object, optionally containing user context retrieved for the last thread message
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"threads/{jsonable_encoder(thread_id)}/messages",
            method="POST",
            json={
                "ignore_roles": ignore_roles,
                "messages": convert_and_respect_annotation_metadata(
                    object_=messages, annotation=typing.Sequence[Message], direction="write"
                ),
                "return_context": return_context,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    AddThreadMessagesResponse,
                    parse_obj_as(
                        type_=AddThreadMessagesResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 500:
                raise InternalServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        types_api_error_ApiError,
                        parse_obj_as(
                            type_=types_api_error_ApiError,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise core_api_error_ApiError(
                status_code=_response.status_code, headers=dict(_response.headers), body=_response.text
            )
        raise core_api_error_ApiError(
            status_code=_response.status_code, headers=dict(_response.headers), body=_response_json
        )
