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

import typing
from ..core.client_wrapper import SyncClientWrapper
from ..common.types.collaborator import Collaborator
from ..core.request_options import RequestOptions
from .types.create_copilot_response import CreateCopilotResponse
from ..core.serialization import convert_and_respect_annotation_metadata
from ..core.pydantic_utilities import parse_obj_as
from json.decoder import JSONDecodeError
from ..core.api_error import ApiError
import uuid
from .types.create_conversation_response import CreateConversationResponse
from .types.message_feedback import MessageFeedback
from .types.input_variable import InputVariable
from .types.send_agent_message_response import SendAgentMessageResponse
from .types.streaming_chunk import StreamingChunk
import httpx_sse
import json
from .types.configuration import Configuration
from .types.delete_copilot_response import DeleteCopilotResponse
from ..core.client_wrapper import AsyncClientWrapper

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


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

    def create_copilot(
        self,
        *,
        name: str,
        description: str,
        collaborators: typing.Sequence[Collaborator],
        request_options: typing.Optional[RequestOptions] = None,
    ) -> CreateCopilotResponse:
        """
        Create a new copilot. The API key used will be added to the copilot for future Requests

        Parameters
        ----------
        name : str
            A descriptive name for the copilot.


        description : str
            An in depth name for the copilot's function. Useful for routing requests to the right copilot.


        collaborators : typing.Sequence[Collaborator]
            A list of collaborator emails and roles that will have access to the copilot.


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

        Returns
        -------
        CreateCopilotResponse

        Examples
        --------
        from credal import CredalApi
        from credal.common import Collaborator

        client = CredalApi(
            api_key="YOUR_API_KEY",
        )
        client.copilots.create_copilot(
            name="Customer Copilot",
            description="This copilot is used to answer customer requests based on internal documentation.",
            collaborators=[
                Collaborator(
                    email="test@gmail.com",
                    role="editor",
                )
            ],
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            "v0/copilots/createCopilot",
            method="POST",
            json={
                "name": name,
                "description": description,
                "collaborators": convert_and_respect_annotation_metadata(
                    object_=collaborators, annotation=typing.Sequence[Collaborator], direction="write"
                ),
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    CreateCopilotResponse,
                    parse_obj_as(
                        type_=CreateCopilotResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def create_conversation(
        self, *, agent_id: uuid.UUID, user_email: str, request_options: typing.Optional[RequestOptions] = None
    ) -> CreateConversationResponse:
        """
        OPTIONAL. Create a new conversation with the Copilot. The conversation ID can be used in the `sendMessage` endpoint. The `sendMessage` endpoint automatically creates new conversations upon first request, but calling this endpoint can simplify certain use cases where it is helpful for the application to have the conversation ID before the first message is sent.

        Parameters
        ----------
        agent_id : uuid.UUID
            Credal-generated Copilot ID to specify which agent to route the request to.


        user_email : str
            End-user for the conversation.


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

        Returns
        -------
        CreateConversationResponse

        Examples
        --------
        import uuid

        from credal import CredalApi

        client = CredalApi(
            api_key="YOUR_API_KEY",
        )
        client.copilots.create_conversation(
            agent_id=uuid.UUID(
                "82e4b12a-6990-45d4-8ebd-85c00e030c24",
            ),
            user_email="ravin@credal.ai",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            "v0/copilots/createConversation",
            method="POST",
            json={
                "agentId": agent_id,
                "userEmail": user_email,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    CreateConversationResponse,
                    parse_obj_as(
                        type_=CreateConversationResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def provide_message_feedback(
        self,
        *,
        agent_id: uuid.UUID,
        user_email: str,
        message_id: uuid.UUID,
        message_feedback: MessageFeedback,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> None:
        """
        Parameters
        ----------
        agent_id : uuid.UUID
            Credal-generated Copilot ID to specify which agent to route the request to.


        user_email : str
            The user profile you want to use when providing feedback.


        message_id : uuid.UUID
            The message ID for which feedback is being provided.


        message_feedback : MessageFeedback
            The feedback provided by the user.


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

        Returns
        -------
        None

        Examples
        --------
        import uuid

        from credal import CredalApi
        from credal.copilots import MessageFeedback

        client = CredalApi(
            api_key="YOUR_API_KEY",
        )
        client.copilots.provide_message_feedback(
            user_email="ravin@credal.ai",
            message_id=uuid.UUID(
                "dd721cd8-4bf2-4b94-9869-258df3dab9dc",
            ),
            agent_id=uuid.UUID(
                "82e4b12a-6990-45d4-8ebd-85c00e030c24",
            ),
            message_feedback=MessageFeedback(
                feedback="NEGATIVE",
                suggested_answer="Yes, Credal is SOC 2 compliant.",
                descriptive_feedback="The response should be extremely clear and concise.",
            ),
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            "v0/copilots/provideMessageFeedback",
            method="POST",
            json={
                "agentId": agent_id,
                "userEmail": user_email,
                "messageId": message_id,
                "messageFeedback": convert_and_respect_annotation_metadata(
                    object_=message_feedback, annotation=MessageFeedback, direction="write"
                ),
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def send_message(
        self,
        *,
        agent_id: uuid.UUID,
        message: str,
        user_email: str,
        conversation_id: typing.Optional[uuid.UUID] = OMIT,
        input_variables: typing.Optional[typing.Sequence[InputVariable]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> SendAgentMessageResponse:
        """
        Parameters
        ----------
        agent_id : uuid.UUID
            Credal-generated Copilot ID to specify which agent to route the request to.


        message : str
            The message you want to send to your copilot.


        user_email : str
            The user profile you want to use when sending the message.


        conversation_id : typing.Optional[uuid.UUID]
            Credal-generated conversation ID for sending follow up messages. Conversation ID is returned after initial message. Optional, to be left off for first messages on new conversations.


        input_variables : typing.Optional[typing.Sequence[InputVariable]]
            Optional input variables to be used in the message. Map the name of the variable to a list of urls.


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

        Returns
        -------
        SendAgentMessageResponse

        Examples
        --------
        import uuid

        from credal import CredalApi
        from credal.copilots import InputVariable

        client = CredalApi(
            api_key="YOUR_API_KEY",
        )
        client.copilots.send_message(
            agent_id=uuid.UUID(
                "82e4b12a-6990-45d4-8ebd-85c00e030c24",
            ),
            message="Is Credal SOC 2 compliant?",
            user_email="ravin@credal.ai",
            input_variables=[
                InputVariable(
                    name="input1",
                    ids=[
                        uuid.UUID(
                            "82e4b12a-6990-45d4-8ebd-85c00e030c24",
                        )
                    ],
                ),
                InputVariable(
                    name="input2",
                    ids=[
                        uuid.UUID(
                            "82e4b12a-6990-45d4-8ebd-85c00e030c25",
                        ),
                        uuid.UUID(
                            "82e4b12a-6990-45d4-8ebd-85c00e030c26",
                        ),
                    ],
                ),
            ],
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            "v0/copilots/sendMessage",
            method="POST",
            json={
                "agentId": agent_id,
                "message": message,
                "userEmail": user_email,
                "conversationId": conversation_id,
                "inputVariables": convert_and_respect_annotation_metadata(
                    object_=input_variables, annotation=typing.Sequence[InputVariable], direction="write"
                ),
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    SendAgentMessageResponse,
                    parse_obj_as(
                        type_=SendAgentMessageResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def stream_message(
        self,
        *,
        copilot_id: uuid.UUID,
        message: str,
        email: str,
        conversation_id: typing.Optional[uuid.UUID] = OMIT,
        input_variables: typing.Optional[typing.Sequence[InputVariable]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.Iterator[StreamingChunk]:
        """
        This endpoint allows you to send a message to a specific copilot and get the response back as a streamed set of Server-Sent Events.

        Parameters
        ----------
        copilot_id : uuid.UUID
            Credal-generated Copilot ID to specify which agent to route the request to.


        message : str
            The message you want to send to your copilot.


        email : str
            The user profile you want to use when sending the message.


        conversation_id : typing.Optional[uuid.UUID]
            Credal-generated conversation ID for sending follow up messages. Conversation ID is returned after initial message. Optional, to be left off for first messages on new conversations.


        input_variables : typing.Optional[typing.Sequence[InputVariable]]
            Optional input variables to be used in the message. Map the name of the variable to a list of urls.


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

        Yields
        ------
        typing.Iterator[StreamingChunk]
            This endpoint returns a stream of server sent events. These can be in two formats - one is an initial event, followed by multiple data chunks, followed by a final chunk, or the other format is just one blocked event. See the examples for more details.


        Examples
        --------
        import uuid

        from credal import CredalApi
        from credal.copilots import InputVariable

        client = CredalApi(
            api_key="YOUR_API_KEY",
        )
        response = client.copilots.stream_message(
            copilot_id=uuid.UUID(
                "82e4b12a-6990-45d4-8ebd-85c00e030c24",
            ),
            message="Is Credal SOC 2 compliant?",
            email="ravin@credal.ai",
            input_variables=[
                InputVariable(
                    name="input1",
                    ids=[
                        uuid.UUID(
                            "82e4b12a-6990-45d4-8ebd-85c00e030c24",
                        )
                    ],
                ),
                InputVariable(
                    name="input2",
                    ids=[
                        uuid.UUID(
                            "82e4b12a-6990-45d4-8ebd-85c00e030c25",
                        ),
                        uuid.UUID(
                            "82e4b12a-6990-45d4-8ebd-85c00e030c26",
                        ),
                    ],
                ),
            ],
        )
        for chunk in response:
            yield chunk
        """
        with self._client_wrapper.httpx_client.stream(
            "v0/copilots/streamMessage",
            method="POST",
            json={
                "copilotId": copilot_id,
                "message": message,
                "email": email,
                "conversationId": conversation_id,
                "inputVariables": convert_and_respect_annotation_metadata(
                    object_=input_variables, annotation=typing.Sequence[InputVariable], direction="write"
                ),
            },
            request_options=request_options,
            omit=OMIT,
        ) as _response:
            try:
                if 200 <= _response.status_code < 300:
                    _event_source = httpx_sse.EventSource(_response)
                    for _sse in _event_source.iter_sse():
                        try:
                            yield typing.cast(
                                StreamingChunk,
                                parse_obj_as(
                                    type_=StreamingChunk,  # type: ignore
                                    object_=json.loads(_sse.data),
                                ),
                            )
                        except:
                            pass
                    return
                _response.read()
                _response_json = _response.json()
            except JSONDecodeError:
                raise ApiError(status_code=_response.status_code, body=_response.text)
            raise ApiError(status_code=_response.status_code, body=_response_json)

    def add_collection_to_copilot(
        self,
        *,
        copilot_id: uuid.UUID,
        collection_id: uuid.UUID,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> None:
        """
        Link a collection with a copilot. The API Key used must be added to both the collection and the copilot beforehand.

        Parameters
        ----------
        copilot_id : uuid.UUID
            Credal-generated copilot ID to add the collection to.


        collection_id : uuid.UUID
            Credal-generated collection ID to add.


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

        Returns
        -------
        None

        Examples
        --------
        import uuid

        from credal import CredalApi

        client = CredalApi(
            api_key="YOUR_API_KEY",
        )
        client.copilots.add_collection_to_copilot(
            copilot_id=uuid.UUID(
                "82e4b12a-6990-45d4-8ebd-85c00e030c24",
            ),
            collection_id=uuid.UUID(
                "def1055f-83c5-43d6-b558-f7a38e7b299e",
            ),
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            "v0/copilots/addCollectionToCopilot",
            method="POST",
            json={
                "copilotId": copilot_id,
                "collectionId": collection_id,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def remove_collection_from_copilot(
        self,
        *,
        copilot_id: uuid.UUID,
        collection_id: uuid.UUID,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> None:
        """
        Unlink a collection with a copilot. The API Key used must be added to both the collection and the copilot beforehand.

        Parameters
        ----------
        copilot_id : uuid.UUID
            Credal-generated copilot ID to add the collection to.


        collection_id : uuid.UUID
            Credal-generated collection ID to add.


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

        Returns
        -------
        None

        Examples
        --------
        import uuid

        from credal import CredalApi

        client = CredalApi(
            api_key="YOUR_API_KEY",
        )
        client.copilots.remove_collection_from_copilot(
            copilot_id=uuid.UUID(
                "82e4b12a-6990-45d4-8ebd-85c00e030c24",
            ),
            collection_id=uuid.UUID(
                "def1055f-83c5-43d6-b558-f7a38e7b299e",
            ),
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            "v0/copilots/removeCollectionFromCopilot",
            method="POST",
            json={
                "copilotId": copilot_id,
                "collectionId": collection_id,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def update_configuration(
        self,
        *,
        copilot_id: uuid.UUID,
        configuration: Configuration,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> None:
        """
        Update the configuration for a copilot

        Parameters
        ----------
        copilot_id : uuid.UUID
            Credal-generated copilot ID to add the collection to.


        configuration : Configuration

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

        Returns
        -------
        None

        Examples
        --------
        import uuid

        from credal import CredalApi
        from credal.copilots import AiEndpointConfiguration, Configuration

        client = CredalApi(
            api_key="YOUR_API_KEY",
        )
        client.copilots.update_configuration(
            copilot_id=uuid.UUID(
                "82e4b12a-6990-45d4-8ebd-85c00e030c24",
            ),
            configuration=Configuration(
                name="Customer Copilot",
                description="This copilot is used to answer customer requests based on internal documentation.",
                prompt="You are a polite, helpful assistant used to answer customer requests.",
                ai_endpoint_configuration=AiEndpointConfiguration(
                    base_url="https://api.openai.com/v1/",
                    api_key="<YOUR_API_KEY_HERE>",
                ),
            ),
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            "v0/copilots/updateConfiguration",
            method="POST",
            json={
                "copilotId": copilot_id,
                "configuration": convert_and_respect_annotation_metadata(
                    object_=configuration, annotation=Configuration, direction="write"
                ),
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def delete_copilot(
        self, *, id: uuid.UUID, request_options: typing.Optional[RequestOptions] = None
    ) -> DeleteCopilotResponse:
        """
        Parameters
        ----------
        id : uuid.UUID
            Copilot ID

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

        Returns
        -------
        DeleteCopilotResponse

        Examples
        --------
        import uuid

        from credal import CredalApi

        client = CredalApi(
            api_key="YOUR_API_KEY",
        )
        client.copilots.delete_copilot(
            id=uuid.UUID(
                "ac20e6ba-0bae-11ef-b25a-efca73df4c3a",
            ),
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            "v0/copilots/deleteCopilot",
            method="DELETE",
            json={
                "id": id,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    DeleteCopilotResponse,
                    parse_obj_as(
                        type_=DeleteCopilotResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)


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

    async def create_copilot(
        self,
        *,
        name: str,
        description: str,
        collaborators: typing.Sequence[Collaborator],
        request_options: typing.Optional[RequestOptions] = None,
    ) -> CreateCopilotResponse:
        """
        Create a new copilot. The API key used will be added to the copilot for future Requests

        Parameters
        ----------
        name : str
            A descriptive name for the copilot.


        description : str
            An in depth name for the copilot's function. Useful for routing requests to the right copilot.


        collaborators : typing.Sequence[Collaborator]
            A list of collaborator emails and roles that will have access to the copilot.


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

        Returns
        -------
        CreateCopilotResponse

        Examples
        --------
        import asyncio

        from credal import AsyncCredalApi
        from credal.common import Collaborator

        client = AsyncCredalApi(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.copilots.create_copilot(
                name="Customer Copilot",
                description="This copilot is used to answer customer requests based on internal documentation.",
                collaborators=[
                    Collaborator(
                        email="test@gmail.com",
                        role="editor",
                    )
                ],
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v0/copilots/createCopilot",
            method="POST",
            json={
                "name": name,
                "description": description,
                "collaborators": convert_and_respect_annotation_metadata(
                    object_=collaborators, annotation=typing.Sequence[Collaborator], direction="write"
                ),
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    CreateCopilotResponse,
                    parse_obj_as(
                        type_=CreateCopilotResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def create_conversation(
        self, *, agent_id: uuid.UUID, user_email: str, request_options: typing.Optional[RequestOptions] = None
    ) -> CreateConversationResponse:
        """
        OPTIONAL. Create a new conversation with the Copilot. The conversation ID can be used in the `sendMessage` endpoint. The `sendMessage` endpoint automatically creates new conversations upon first request, but calling this endpoint can simplify certain use cases where it is helpful for the application to have the conversation ID before the first message is sent.

        Parameters
        ----------
        agent_id : uuid.UUID
            Credal-generated Copilot ID to specify which agent to route the request to.


        user_email : str
            End-user for the conversation.


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

        Returns
        -------
        CreateConversationResponse

        Examples
        --------
        import asyncio
        import uuid

        from credal import AsyncCredalApi

        client = AsyncCredalApi(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.copilots.create_conversation(
                agent_id=uuid.UUID(
                    "82e4b12a-6990-45d4-8ebd-85c00e030c24",
                ),
                user_email="ravin@credal.ai",
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v0/copilots/createConversation",
            method="POST",
            json={
                "agentId": agent_id,
                "userEmail": user_email,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    CreateConversationResponse,
                    parse_obj_as(
                        type_=CreateConversationResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def provide_message_feedback(
        self,
        *,
        agent_id: uuid.UUID,
        user_email: str,
        message_id: uuid.UUID,
        message_feedback: MessageFeedback,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> None:
        """
        Parameters
        ----------
        agent_id : uuid.UUID
            Credal-generated Copilot ID to specify which agent to route the request to.


        user_email : str
            The user profile you want to use when providing feedback.


        message_id : uuid.UUID
            The message ID for which feedback is being provided.


        message_feedback : MessageFeedback
            The feedback provided by the user.


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

        Returns
        -------
        None

        Examples
        --------
        import asyncio
        import uuid

        from credal import AsyncCredalApi
        from credal.copilots import MessageFeedback

        client = AsyncCredalApi(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.copilots.provide_message_feedback(
                user_email="ravin@credal.ai",
                message_id=uuid.UUID(
                    "dd721cd8-4bf2-4b94-9869-258df3dab9dc",
                ),
                agent_id=uuid.UUID(
                    "82e4b12a-6990-45d4-8ebd-85c00e030c24",
                ),
                message_feedback=MessageFeedback(
                    feedback="NEGATIVE",
                    suggested_answer="Yes, Credal is SOC 2 compliant.",
                    descriptive_feedback="The response should be extremely clear and concise.",
                ),
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v0/copilots/provideMessageFeedback",
            method="POST",
            json={
                "agentId": agent_id,
                "userEmail": user_email,
                "messageId": message_id,
                "messageFeedback": convert_and_respect_annotation_metadata(
                    object_=message_feedback, annotation=MessageFeedback, direction="write"
                ),
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def send_message(
        self,
        *,
        agent_id: uuid.UUID,
        message: str,
        user_email: str,
        conversation_id: typing.Optional[uuid.UUID] = OMIT,
        input_variables: typing.Optional[typing.Sequence[InputVariable]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> SendAgentMessageResponse:
        """
        Parameters
        ----------
        agent_id : uuid.UUID
            Credal-generated Copilot ID to specify which agent to route the request to.


        message : str
            The message you want to send to your copilot.


        user_email : str
            The user profile you want to use when sending the message.


        conversation_id : typing.Optional[uuid.UUID]
            Credal-generated conversation ID for sending follow up messages. Conversation ID is returned after initial message. Optional, to be left off for first messages on new conversations.


        input_variables : typing.Optional[typing.Sequence[InputVariable]]
            Optional input variables to be used in the message. Map the name of the variable to a list of urls.


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

        Returns
        -------
        SendAgentMessageResponse

        Examples
        --------
        import asyncio
        import uuid

        from credal import AsyncCredalApi
        from credal.copilots import InputVariable

        client = AsyncCredalApi(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.copilots.send_message(
                agent_id=uuid.UUID(
                    "82e4b12a-6990-45d4-8ebd-85c00e030c24",
                ),
                message="Is Credal SOC 2 compliant?",
                user_email="ravin@credal.ai",
                input_variables=[
                    InputVariable(
                        name="input1",
                        ids=[
                            uuid.UUID(
                                "82e4b12a-6990-45d4-8ebd-85c00e030c24",
                            )
                        ],
                    ),
                    InputVariable(
                        name="input2",
                        ids=[
                            uuid.UUID(
                                "82e4b12a-6990-45d4-8ebd-85c00e030c25",
                            ),
                            uuid.UUID(
                                "82e4b12a-6990-45d4-8ebd-85c00e030c26",
                            ),
                        ],
                    ),
                ],
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v0/copilots/sendMessage",
            method="POST",
            json={
                "agentId": agent_id,
                "message": message,
                "userEmail": user_email,
                "conversationId": conversation_id,
                "inputVariables": convert_and_respect_annotation_metadata(
                    object_=input_variables, annotation=typing.Sequence[InputVariable], direction="write"
                ),
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    SendAgentMessageResponse,
                    parse_obj_as(
                        type_=SendAgentMessageResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def stream_message(
        self,
        *,
        copilot_id: uuid.UUID,
        message: str,
        email: str,
        conversation_id: typing.Optional[uuid.UUID] = OMIT,
        input_variables: typing.Optional[typing.Sequence[InputVariable]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.AsyncIterator[StreamingChunk]:
        """
        This endpoint allows you to send a message to a specific copilot and get the response back as a streamed set of Server-Sent Events.

        Parameters
        ----------
        copilot_id : uuid.UUID
            Credal-generated Copilot ID to specify which agent to route the request to.


        message : str
            The message you want to send to your copilot.


        email : str
            The user profile you want to use when sending the message.


        conversation_id : typing.Optional[uuid.UUID]
            Credal-generated conversation ID for sending follow up messages. Conversation ID is returned after initial message. Optional, to be left off for first messages on new conversations.


        input_variables : typing.Optional[typing.Sequence[InputVariable]]
            Optional input variables to be used in the message. Map the name of the variable to a list of urls.


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

        Yields
        ------
        typing.AsyncIterator[StreamingChunk]
            This endpoint returns a stream of server sent events. These can be in two formats - one is an initial event, followed by multiple data chunks, followed by a final chunk, or the other format is just one blocked event. See the examples for more details.


        Examples
        --------
        import asyncio
        import uuid

        from credal import AsyncCredalApi
        from credal.copilots import InputVariable

        client = AsyncCredalApi(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            response = await client.copilots.stream_message(
                copilot_id=uuid.UUID(
                    "82e4b12a-6990-45d4-8ebd-85c00e030c24",
                ),
                message="Is Credal SOC 2 compliant?",
                email="ravin@credal.ai",
                input_variables=[
                    InputVariable(
                        name="input1",
                        ids=[
                            uuid.UUID(
                                "82e4b12a-6990-45d4-8ebd-85c00e030c24",
                            )
                        ],
                    ),
                    InputVariable(
                        name="input2",
                        ids=[
                            uuid.UUID(
                                "82e4b12a-6990-45d4-8ebd-85c00e030c25",
                            ),
                            uuid.UUID(
                                "82e4b12a-6990-45d4-8ebd-85c00e030c26",
                            ),
                        ],
                    ),
                ],
            )
            async for chunk in response:
                yield chunk


        asyncio.run(main())
        """
        async with self._client_wrapper.httpx_client.stream(
            "v0/copilots/streamMessage",
            method="POST",
            json={
                "copilotId": copilot_id,
                "message": message,
                "email": email,
                "conversationId": conversation_id,
                "inputVariables": convert_and_respect_annotation_metadata(
                    object_=input_variables, annotation=typing.Sequence[InputVariable], direction="write"
                ),
            },
            request_options=request_options,
            omit=OMIT,
        ) as _response:
            try:
                if 200 <= _response.status_code < 300:
                    _event_source = httpx_sse.EventSource(_response)
                    async for _sse in _event_source.aiter_sse():
                        try:
                            yield typing.cast(
                                StreamingChunk,
                                parse_obj_as(
                                    type_=StreamingChunk,  # type: ignore
                                    object_=json.loads(_sse.data),
                                ),
                            )
                        except:
                            pass
                    return
                await _response.aread()
                _response_json = _response.json()
            except JSONDecodeError:
                raise ApiError(status_code=_response.status_code, body=_response.text)
            raise ApiError(status_code=_response.status_code, body=_response_json)

    async def add_collection_to_copilot(
        self,
        *,
        copilot_id: uuid.UUID,
        collection_id: uuid.UUID,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> None:
        """
        Link a collection with a copilot. The API Key used must be added to both the collection and the copilot beforehand.

        Parameters
        ----------
        copilot_id : uuid.UUID
            Credal-generated copilot ID to add the collection to.


        collection_id : uuid.UUID
            Credal-generated collection ID to add.


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

        Returns
        -------
        None

        Examples
        --------
        import asyncio
        import uuid

        from credal import AsyncCredalApi

        client = AsyncCredalApi(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.copilots.add_collection_to_copilot(
                copilot_id=uuid.UUID(
                    "82e4b12a-6990-45d4-8ebd-85c00e030c24",
                ),
                collection_id=uuid.UUID(
                    "def1055f-83c5-43d6-b558-f7a38e7b299e",
                ),
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v0/copilots/addCollectionToCopilot",
            method="POST",
            json={
                "copilotId": copilot_id,
                "collectionId": collection_id,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def remove_collection_from_copilot(
        self,
        *,
        copilot_id: uuid.UUID,
        collection_id: uuid.UUID,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> None:
        """
        Unlink a collection with a copilot. The API Key used must be added to both the collection and the copilot beforehand.

        Parameters
        ----------
        copilot_id : uuid.UUID
            Credal-generated copilot ID to add the collection to.


        collection_id : uuid.UUID
            Credal-generated collection ID to add.


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

        Returns
        -------
        None

        Examples
        --------
        import asyncio
        import uuid

        from credal import AsyncCredalApi

        client = AsyncCredalApi(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.copilots.remove_collection_from_copilot(
                copilot_id=uuid.UUID(
                    "82e4b12a-6990-45d4-8ebd-85c00e030c24",
                ),
                collection_id=uuid.UUID(
                    "def1055f-83c5-43d6-b558-f7a38e7b299e",
                ),
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v0/copilots/removeCollectionFromCopilot",
            method="POST",
            json={
                "copilotId": copilot_id,
                "collectionId": collection_id,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def update_configuration(
        self,
        *,
        copilot_id: uuid.UUID,
        configuration: Configuration,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> None:
        """
        Update the configuration for a copilot

        Parameters
        ----------
        copilot_id : uuid.UUID
            Credal-generated copilot ID to add the collection to.


        configuration : Configuration

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

        Returns
        -------
        None

        Examples
        --------
        import asyncio
        import uuid

        from credal import AsyncCredalApi
        from credal.copilots import AiEndpointConfiguration, Configuration

        client = AsyncCredalApi(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.copilots.update_configuration(
                copilot_id=uuid.UUID(
                    "82e4b12a-6990-45d4-8ebd-85c00e030c24",
                ),
                configuration=Configuration(
                    name="Customer Copilot",
                    description="This copilot is used to answer customer requests based on internal documentation.",
                    prompt="You are a polite, helpful assistant used to answer customer requests.",
                    ai_endpoint_configuration=AiEndpointConfiguration(
                        base_url="https://api.openai.com/v1/",
                        api_key="<YOUR_API_KEY_HERE>",
                    ),
                ),
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v0/copilots/updateConfiguration",
            method="POST",
            json={
                "copilotId": copilot_id,
                "configuration": convert_and_respect_annotation_metadata(
                    object_=configuration, annotation=Configuration, direction="write"
                ),
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def delete_copilot(
        self, *, id: uuid.UUID, request_options: typing.Optional[RequestOptions] = None
    ) -> DeleteCopilotResponse:
        """
        Parameters
        ----------
        id : uuid.UUID
            Copilot ID

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

        Returns
        -------
        DeleteCopilotResponse

        Examples
        --------
        import asyncio
        import uuid

        from credal import AsyncCredalApi

        client = AsyncCredalApi(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.copilots.delete_copilot(
                id=uuid.UUID(
                    "ac20e6ba-0bae-11ef-b25a-efca73df4c3a",
                ),
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v0/copilots/deleteCopilot",
            method="DELETE",
            json={
                "id": id,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    DeleteCopilotResponse,
                    parse_obj_as(
                        type_=DeleteCopilotResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)
