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

import typing

from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ..core.request_options import RequestOptions
from .prompts.client import AsyncPromptsClient, PromptsClient
from .raw_client import AsyncRawAgentClient, RawAgentClient
from .types.agent_chat_response import AgentChatResponse
from .types.agent_create_request_provider import AgentCreateRequestProvider
from .types.agent_delete_response import AgentDeleteResponse
from .types.agent_get_chat_messages_request_order import AgentGetChatMessagesRequestOrder
from .types.agent_get_chat_messages_request_role import AgentGetChatMessagesRequestRole
from .types.agent_get_chat_messages_response import AgentGetChatMessagesResponse
from .types.agent_list_response import AgentListResponse
from .types.agent_response import AgentResponse
from .types.json_patch import JsonPatch

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


class AgentClient:
    def __init__(self, *, client_wrapper: SyncClientWrapper):
        self._raw_client = RawAgentClient(client_wrapper=client_wrapper)
        self.prompts = PromptsClient(client_wrapper=client_wrapper)

    @property
    def with_raw_response(self) -> RawAgentClient:
        """
        Retrieves a raw implementation of this client that returns raw responses.

        Returns
        -------
        RawAgentClient
        """
        return self._raw_client

    def create(
        self,
        *,
        name: str,
        prompts: typing.Sequence[str],
        provider: AgentCreateRequestProvider,
        description: typing.Optional[str] = OMIT,
        tools: typing.Optional[typing.Sequence[str]] = OMIT,
        tags: typing.Optional[typing.Sequence[str]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AgentResponse:
        """
        Creates a new PhenoAgent with specified configuration

        Parameters
        ----------
        name : str
            Agent name

        prompts : typing.Sequence[str]
            Array of prompt IDs to use for this agent

        provider : AgentCreateRequestProvider
            FHIR provider ID(s) for this agent. Required.
            In shared/experiment environments, the default sandbox provider is used if a different provider is not explicitly specified.

        description : typing.Optional[str]
            Agent description

        tools : typing.Optional[typing.Sequence[str]]
            Array of MCP server tool IDs to use for this agent

        tags : typing.Optional[typing.Sequence[str]]
            Tags for categorizing the agent

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

        Returns
        -------
        AgentResponse
            Agent created successfully

        Examples
        --------
        from phenoml import phenoml

        client = phenoml(
            token="YOUR_TOKEN",
        )
        client.agent.create(
            name="name",
            prompts=["prompt_123", "prompt_456"],
            provider="provider",
        )
        """
        _response = self._raw_client.create(
            name=name,
            prompts=prompts,
            provider=provider,
            description=description,
            tools=tools,
            tags=tags,
            request_options=request_options,
        )
        return _response.data

    def list(
        self, *, tags: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None
    ) -> AgentListResponse:
        """
        Retrieves a list of PhenoAgents belonging to the authenticated user

        Parameters
        ----------
        tags : typing.Optional[str]
            Filter by tags

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

        Returns
        -------
        AgentListResponse
            Agents retrieved successfully

        Examples
        --------
        from phenoml import phenoml

        client = phenoml(
            token="YOUR_TOKEN",
        )
        client.agent.list(
            tags="tags",
        )
        """
        _response = self._raw_client.list(tags=tags, request_options=request_options)
        return _response.data

    def get(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> AgentResponse:
        """
        Retrieves a specific agent by its ID

        Parameters
        ----------
        id : str
            Agent ID

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

        Returns
        -------
        AgentResponse
            Agent retrieved successfully

        Examples
        --------
        from phenoml import phenoml

        client = phenoml(
            token="YOUR_TOKEN",
        )
        client.agent.get(
            id="id",
        )
        """
        _response = self._raw_client.get(id, request_options=request_options)
        return _response.data

    def update(
        self,
        id: str,
        *,
        name: str,
        prompts: typing.Sequence[str],
        provider: AgentCreateRequestProvider,
        description: typing.Optional[str] = OMIT,
        tools: typing.Optional[typing.Sequence[str]] = OMIT,
        tags: typing.Optional[typing.Sequence[str]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AgentResponse:
        """
        Updates an existing agent's configuration

        Parameters
        ----------
        id : str
            Agent ID

        name : str
            Agent name

        prompts : typing.Sequence[str]
            Array of prompt IDs to use for this agent

        provider : AgentCreateRequestProvider
            FHIR provider ID(s) for this agent. Required.
            In shared/experiment environments, the default sandbox provider is used if a different provider is not explicitly specified.

        description : typing.Optional[str]
            Agent description

        tools : typing.Optional[typing.Sequence[str]]
            Array of MCP server tool IDs to use for this agent

        tags : typing.Optional[typing.Sequence[str]]
            Tags for categorizing the agent

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

        Returns
        -------
        AgentResponse
            Agent updated successfully

        Examples
        --------
        from phenoml import phenoml

        client = phenoml(
            token="YOUR_TOKEN",
        )
        client.agent.update(
            id="id",
            name="name",
            prompts=["prompt_123", "prompt_456"],
            provider="provider",
        )
        """
        _response = self._raw_client.update(
            id,
            name=name,
            prompts=prompts,
            provider=provider,
            description=description,
            tools=tools,
            tags=tags,
            request_options=request_options,
        )
        return _response.data

    def delete(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> AgentDeleteResponse:
        """
        Deletes an existing agent

        Parameters
        ----------
        id : str
            Agent ID

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

        Returns
        -------
        AgentDeleteResponse
            Agent deleted successfully

        Examples
        --------
        from phenoml import phenoml

        client = phenoml(
            token="YOUR_TOKEN",
        )
        client.agent.delete(
            id="id",
        )
        """
        _response = self._raw_client.delete(id, request_options=request_options)
        return _response.data

    def patch(
        self, id: str, *, request: JsonPatch, request_options: typing.Optional[RequestOptions] = None
    ) -> AgentResponse:
        """
        Patches an existing agent's configuration

        Parameters
        ----------
        id : str
            Agent ID

        request : JsonPatch

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

        Returns
        -------
        AgentResponse
            Agent patched successfully

        Examples
        --------
        from phenoml import phenoml
        from phenoml.agent import JsonPatchOperation

        client = phenoml(
            token="YOUR_TOKEN",
        )
        client.agent.patch(
            id="id",
            request=[
                JsonPatchOperation(
                    op="replace",
                    path="/name",
                    value="Updated Agent Name",
                ),
                JsonPatchOperation(
                    op="add",
                    path="/tags/-",
                    value="new-tag",
                ),
                JsonPatchOperation(
                    op="remove",
                    path="/description",
                ),
            ],
        )
        """
        _response = self._raw_client.patch(id, request=request, request_options=request_options)
        return _response.data

    def chat(
        self,
        *,
        message: str,
        agent_id: str,
        phenoml_on_behalf_of: typing.Optional[str] = None,
        phenoml_fhir_provider: typing.Optional[str] = None,
        context: typing.Optional[str] = OMIT,
        session_id: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AgentChatResponse:
        """
        Send a message to an agent and receive a response

        Parameters
        ----------
        message : str
            The message to send to the agent

        agent_id : str
            The ID of the agent to chat with

        phenoml_on_behalf_of : typing.Optional[str]
            Optional header for on-behalf-of authentication. Used when making requests on behalf of another user or entity.
            Must be in the format: Patient/{uuid} or Practitioner/{uuid}

        phenoml_fhir_provider : typing.Optional[str]
            Optional header for FHIR provider authentication. Contains credentials in the format {fhir_provider_id}:{oauth2_token}.
            Multiple FHIR provider integrations can be provided as comma-separated values.

        context : typing.Optional[str]
            Optional context for the conversation

        session_id : typing.Optional[str]
            Optional session ID for conversation continuity

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

        Returns
        -------
        AgentChatResponse
            Chat response received successfully

        Examples
        --------
        from phenoml import phenoml

        client = phenoml(
            token="YOUR_TOKEN",
        )
        client.agent.chat(
            phenoml_on_behalf_of="Patient/550e8400-e29b-41d4-a716-446655440000",
            phenoml_fhir_provider="550e8400-e29b-41d4-a716-446655440000:eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c...",
            message="What is the patient's current condition?",
            agent_id="agent-123",
        )
        """
        _response = self._raw_client.chat(
            message=message,
            agent_id=agent_id,
            phenoml_on_behalf_of=phenoml_on_behalf_of,
            phenoml_fhir_provider=phenoml_fhir_provider,
            context=context,
            session_id=session_id,
            request_options=request_options,
        )
        return _response.data

    def get_chat_messages(
        self,
        *,
        chat_session_id: str,
        num_messages: typing.Optional[int] = None,
        role: typing.Optional[AgentGetChatMessagesRequestRole] = None,
        order: typing.Optional[AgentGetChatMessagesRequestOrder] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AgentGetChatMessagesResponse:
        """
        Retrieves a list of chat messages for a given chat session

        Parameters
        ----------
        chat_session_id : str
            Chat session ID

        num_messages : typing.Optional[int]
            Number of messages to return

        role : typing.Optional[AgentGetChatMessagesRequestRole]
            Filter by one or more message roles. Multiple roles can be specified as a comma-separated string.
            If not specified, messages with all roles are returned.

            **Available roles:**
            - `user` - Messages from the user
            - `assistant` - Text responses from the AI assistant
            - `model` - Function/tool call requests from the model
            - `function` - Function/tool call results

        order : typing.Optional[AgentGetChatMessagesRequestOrder]
            Order of messages

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

        Returns
        -------
        AgentGetChatMessagesResponse
            Chat messages retrieved successfully

        Examples
        --------
        from phenoml import phenoml

        client = phenoml(
            token="YOUR_TOKEN",
        )
        client.agent.get_chat_messages(
            chat_session_id="chat_session_id",
            num_messages=1,
            role="user",
            order="asc",
        )
        """
        _response = self._raw_client.get_chat_messages(
            chat_session_id=chat_session_id,
            num_messages=num_messages,
            role=role,
            order=order,
            request_options=request_options,
        )
        return _response.data


class AsyncAgentClient:
    def __init__(self, *, client_wrapper: AsyncClientWrapper):
        self._raw_client = AsyncRawAgentClient(client_wrapper=client_wrapper)
        self.prompts = AsyncPromptsClient(client_wrapper=client_wrapper)

    @property
    def with_raw_response(self) -> AsyncRawAgentClient:
        """
        Retrieves a raw implementation of this client that returns raw responses.

        Returns
        -------
        AsyncRawAgentClient
        """
        return self._raw_client

    async def create(
        self,
        *,
        name: str,
        prompts: typing.Sequence[str],
        provider: AgentCreateRequestProvider,
        description: typing.Optional[str] = OMIT,
        tools: typing.Optional[typing.Sequence[str]] = OMIT,
        tags: typing.Optional[typing.Sequence[str]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AgentResponse:
        """
        Creates a new PhenoAgent with specified configuration

        Parameters
        ----------
        name : str
            Agent name

        prompts : typing.Sequence[str]
            Array of prompt IDs to use for this agent

        provider : AgentCreateRequestProvider
            FHIR provider ID(s) for this agent. Required.
            In shared/experiment environments, the default sandbox provider is used if a different provider is not explicitly specified.

        description : typing.Optional[str]
            Agent description

        tools : typing.Optional[typing.Sequence[str]]
            Array of MCP server tool IDs to use for this agent

        tags : typing.Optional[typing.Sequence[str]]
            Tags for categorizing the agent

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

        Returns
        -------
        AgentResponse
            Agent created successfully

        Examples
        --------
        import asyncio

        from phenoml import Asyncphenoml

        client = Asyncphenoml(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.agent.create(
                name="name",
                prompts=["prompt_123", "prompt_456"],
                provider="provider",
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.create(
            name=name,
            prompts=prompts,
            provider=provider,
            description=description,
            tools=tools,
            tags=tags,
            request_options=request_options,
        )
        return _response.data

    async def list(
        self, *, tags: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None
    ) -> AgentListResponse:
        """
        Retrieves a list of PhenoAgents belonging to the authenticated user

        Parameters
        ----------
        tags : typing.Optional[str]
            Filter by tags

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

        Returns
        -------
        AgentListResponse
            Agents retrieved successfully

        Examples
        --------
        import asyncio

        from phenoml import Asyncphenoml

        client = Asyncphenoml(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.agent.list(
                tags="tags",
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.list(tags=tags, request_options=request_options)
        return _response.data

    async def get(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> AgentResponse:
        """
        Retrieves a specific agent by its ID

        Parameters
        ----------
        id : str
            Agent ID

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

        Returns
        -------
        AgentResponse
            Agent retrieved successfully

        Examples
        --------
        import asyncio

        from phenoml import Asyncphenoml

        client = Asyncphenoml(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.agent.get(
                id="id",
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.get(id, request_options=request_options)
        return _response.data

    async def update(
        self,
        id: str,
        *,
        name: str,
        prompts: typing.Sequence[str],
        provider: AgentCreateRequestProvider,
        description: typing.Optional[str] = OMIT,
        tools: typing.Optional[typing.Sequence[str]] = OMIT,
        tags: typing.Optional[typing.Sequence[str]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AgentResponse:
        """
        Updates an existing agent's configuration

        Parameters
        ----------
        id : str
            Agent ID

        name : str
            Agent name

        prompts : typing.Sequence[str]
            Array of prompt IDs to use for this agent

        provider : AgentCreateRequestProvider
            FHIR provider ID(s) for this agent. Required.
            In shared/experiment environments, the default sandbox provider is used if a different provider is not explicitly specified.

        description : typing.Optional[str]
            Agent description

        tools : typing.Optional[typing.Sequence[str]]
            Array of MCP server tool IDs to use for this agent

        tags : typing.Optional[typing.Sequence[str]]
            Tags for categorizing the agent

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

        Returns
        -------
        AgentResponse
            Agent updated successfully

        Examples
        --------
        import asyncio

        from phenoml import Asyncphenoml

        client = Asyncphenoml(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.agent.update(
                id="id",
                name="name",
                prompts=["prompt_123", "prompt_456"],
                provider="provider",
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.update(
            id,
            name=name,
            prompts=prompts,
            provider=provider,
            description=description,
            tools=tools,
            tags=tags,
            request_options=request_options,
        )
        return _response.data

    async def delete(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> AgentDeleteResponse:
        """
        Deletes an existing agent

        Parameters
        ----------
        id : str
            Agent ID

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

        Returns
        -------
        AgentDeleteResponse
            Agent deleted successfully

        Examples
        --------
        import asyncio

        from phenoml import Asyncphenoml

        client = Asyncphenoml(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.agent.delete(
                id="id",
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.delete(id, request_options=request_options)
        return _response.data

    async def patch(
        self, id: str, *, request: JsonPatch, request_options: typing.Optional[RequestOptions] = None
    ) -> AgentResponse:
        """
        Patches an existing agent's configuration

        Parameters
        ----------
        id : str
            Agent ID

        request : JsonPatch

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

        Returns
        -------
        AgentResponse
            Agent patched successfully

        Examples
        --------
        import asyncio

        from phenoml import Asyncphenoml
        from phenoml.agent import JsonPatchOperation

        client = Asyncphenoml(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.agent.patch(
                id="id",
                request=[
                    JsonPatchOperation(
                        op="replace",
                        path="/name",
                        value="Updated Agent Name",
                    ),
                    JsonPatchOperation(
                        op="add",
                        path="/tags/-",
                        value="new-tag",
                    ),
                    JsonPatchOperation(
                        op="remove",
                        path="/description",
                    ),
                ],
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.patch(id, request=request, request_options=request_options)
        return _response.data

    async def chat(
        self,
        *,
        message: str,
        agent_id: str,
        phenoml_on_behalf_of: typing.Optional[str] = None,
        phenoml_fhir_provider: typing.Optional[str] = None,
        context: typing.Optional[str] = OMIT,
        session_id: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AgentChatResponse:
        """
        Send a message to an agent and receive a response

        Parameters
        ----------
        message : str
            The message to send to the agent

        agent_id : str
            The ID of the agent to chat with

        phenoml_on_behalf_of : typing.Optional[str]
            Optional header for on-behalf-of authentication. Used when making requests on behalf of another user or entity.
            Must be in the format: Patient/{uuid} or Practitioner/{uuid}

        phenoml_fhir_provider : typing.Optional[str]
            Optional header for FHIR provider authentication. Contains credentials in the format {fhir_provider_id}:{oauth2_token}.
            Multiple FHIR provider integrations can be provided as comma-separated values.

        context : typing.Optional[str]
            Optional context for the conversation

        session_id : typing.Optional[str]
            Optional session ID for conversation continuity

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

        Returns
        -------
        AgentChatResponse
            Chat response received successfully

        Examples
        --------
        import asyncio

        from phenoml import Asyncphenoml

        client = Asyncphenoml(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.agent.chat(
                phenoml_on_behalf_of="Patient/550e8400-e29b-41d4-a716-446655440000",
                phenoml_fhir_provider="550e8400-e29b-41d4-a716-446655440000:eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c...",
                message="What is the patient's current condition?",
                agent_id="agent-123",
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.chat(
            message=message,
            agent_id=agent_id,
            phenoml_on_behalf_of=phenoml_on_behalf_of,
            phenoml_fhir_provider=phenoml_fhir_provider,
            context=context,
            session_id=session_id,
            request_options=request_options,
        )
        return _response.data

    async def get_chat_messages(
        self,
        *,
        chat_session_id: str,
        num_messages: typing.Optional[int] = None,
        role: typing.Optional[AgentGetChatMessagesRequestRole] = None,
        order: typing.Optional[AgentGetChatMessagesRequestOrder] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AgentGetChatMessagesResponse:
        """
        Retrieves a list of chat messages for a given chat session

        Parameters
        ----------
        chat_session_id : str
            Chat session ID

        num_messages : typing.Optional[int]
            Number of messages to return

        role : typing.Optional[AgentGetChatMessagesRequestRole]
            Filter by one or more message roles. Multiple roles can be specified as a comma-separated string.
            If not specified, messages with all roles are returned.

            **Available roles:**
            - `user` - Messages from the user
            - `assistant` - Text responses from the AI assistant
            - `model` - Function/tool call requests from the model
            - `function` - Function/tool call results

        order : typing.Optional[AgentGetChatMessagesRequestOrder]
            Order of messages

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

        Returns
        -------
        AgentGetChatMessagesResponse
            Chat messages retrieved successfully

        Examples
        --------
        import asyncio

        from phenoml import Asyncphenoml

        client = Asyncphenoml(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.agent.get_chat_messages(
                chat_session_id="chat_session_id",
                num_messages=1,
                role="user",
                order="asc",
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.get_chat_messages(
            chat_session_id=chat_session_id,
            num_messages=num_messages,
            role=role,
            order=order,
            request_options=request_options,
        )
        return _response.data
