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

import datetime as dt
import typing

from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ...core.request_options import RequestOptions
from ...types.archival_memory_search_response import ArchivalMemorySearchResponse
from ...types.passage import Passage
from .raw_client import AsyncRawPassagesClient, RawPassagesClient
from .types.passages_search_request_tag_match_mode import PassagesSearchRequestTagMatchMode

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


class PassagesClient:
    def __init__(self, *, client_wrapper: SyncClientWrapper):
        self._raw_client = RawPassagesClient(client_wrapper=client_wrapper)

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

        Returns
        -------
        RawPassagesClient
        """
        return self._raw_client

    def list(
        self,
        agent_id: str,
        *,
        after: typing.Optional[str] = None,
        before: typing.Optional[str] = None,
        limit: typing.Optional[int] = None,
        search: typing.Optional[str] = None,
        ascending: typing.Optional[bool] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.List[Passage]:
        """
        Retrieve the memories in an agent's archival memory store (paginated query).

        Parameters
        ----------
        agent_id : str

        after : typing.Optional[str]
            Unique ID of the memory to start the query range at.

        before : typing.Optional[str]
            Unique ID of the memory to end the query range at.

        limit : typing.Optional[int]
            How many results to include in the response.

        search : typing.Optional[str]
            Search passages by text

        ascending : typing.Optional[bool]
            Whether to sort passages oldest to newest (True, default) or newest to oldest (False)

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

        Returns
        -------
        typing.List[Passage]
            Successful Response

        Examples
        --------
        from letta_client import Letta

        client = Letta(
            project="YOUR_PROJECT",
            token="YOUR_TOKEN",
        )
        client.agents.passages.list(
            agent_id="agent_id",
        )
        """
        _response = self._raw_client.list(
            agent_id,
            after=after,
            before=before,
            limit=limit,
            search=search,
            ascending=ascending,
            request_options=request_options,
        )
        return _response.data

    def create(
        self,
        agent_id: str,
        *,
        text: str,
        tags: typing.Optional[typing.Sequence[str]] = OMIT,
        created_at: typing.Optional[dt.datetime] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.List[Passage]:
        """
        Insert a memory into an agent's archival memory store.

        Parameters
        ----------
        agent_id : str

        text : str
            Text to write to archival memory.

        tags : typing.Optional[typing.Sequence[str]]
            Optional list of tags to attach to the memory.

        created_at : typing.Optional[dt.datetime]
            Optional timestamp for the memory (defaults to current UTC time).

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

        Returns
        -------
        typing.List[Passage]
            Successful Response

        Examples
        --------
        from letta_client import Letta

        client = Letta(
            project="YOUR_PROJECT",
            token="YOUR_TOKEN",
        )
        client.agents.passages.create(
            agent_id="agent_id",
            text="text",
        )
        """
        _response = self._raw_client.create(
            agent_id, text=text, tags=tags, created_at=created_at, request_options=request_options
        )
        return _response.data

    def search(
        self,
        agent_id: str,
        *,
        query: str,
        tags: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
        tag_match_mode: typing.Optional[PassagesSearchRequestTagMatchMode] = None,
        top_k: typing.Optional[int] = None,
        start_datetime: typing.Optional[dt.datetime] = None,
        end_datetime: typing.Optional[dt.datetime] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ArchivalMemorySearchResponse:
        """
        Search archival memory using semantic (embedding-based) search with optional temporal filtering.

        This endpoint allows manual triggering of archival memory searches, enabling users to query
        an agent's archival memory store directly via the API. The search uses the same functionality
        as the agent's archival_memory_search tool but is accessible for external API usage.

        Parameters
        ----------
        agent_id : str

        query : str
            String to search for using semantic similarity

        tags : typing.Optional[typing.Union[str, typing.Sequence[str]]]
            Optional list of tags to filter search results

        tag_match_mode : typing.Optional[PassagesSearchRequestTagMatchMode]
            How to match tags - 'any' to match passages with any of the tags, 'all' to match only passages with all tags

        top_k : typing.Optional[int]
            Maximum number of results to return. Uses system default if not specified

        start_datetime : typing.Optional[dt.datetime]
            Filter results to passages created after this datetime

        end_datetime : typing.Optional[dt.datetime]
            Filter results to passages created before this datetime

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

        Returns
        -------
        ArchivalMemorySearchResponse
            Successful Response

        Examples
        --------
        from letta_client import Letta

        client = Letta(
            project="YOUR_PROJECT",
            token="YOUR_TOKEN",
        )
        client.agents.passages.search(
            agent_id="agent_id",
            query="query",
        )
        """
        _response = self._raw_client.search(
            agent_id,
            query=query,
            tags=tags,
            tag_match_mode=tag_match_mode,
            top_k=top_k,
            start_datetime=start_datetime,
            end_datetime=end_datetime,
            request_options=request_options,
        )
        return _response.data

    def delete(
        self, agent_id: str, memory_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> typing.Optional[typing.Any]:
        """
        Delete a memory from an agent's archival memory store.

        Parameters
        ----------
        agent_id : str

        memory_id : str

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

        Returns
        -------
        typing.Optional[typing.Any]
            Successful Response

        Examples
        --------
        from letta_client import Letta

        client = Letta(
            project="YOUR_PROJECT",
            token="YOUR_TOKEN",
        )
        client.agents.passages.delete(
            agent_id="agent_id",
            memory_id="memory_id",
        )
        """
        _response = self._raw_client.delete(agent_id, memory_id, request_options=request_options)
        return _response.data

    def modify(self, agent_id: str, memory_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None:
        """
        Parameters
        ----------
        agent_id : str

        memory_id : str

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

        Returns
        -------
        None

        Examples
        --------
        from letta_client import Letta

        client = Letta(
            project="YOUR_PROJECT",
            token="YOUR_TOKEN",
        )
        client.agents.passages.modify(
            agent_id="agent_id",
            memory_id="memory_id",
        )
        """
        _response = self._raw_client.modify(agent_id, memory_id, request_options=request_options)
        return _response.data


class AsyncPassagesClient:
    def __init__(self, *, client_wrapper: AsyncClientWrapper):
        self._raw_client = AsyncRawPassagesClient(client_wrapper=client_wrapper)

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

        Returns
        -------
        AsyncRawPassagesClient
        """
        return self._raw_client

    async def list(
        self,
        agent_id: str,
        *,
        after: typing.Optional[str] = None,
        before: typing.Optional[str] = None,
        limit: typing.Optional[int] = None,
        search: typing.Optional[str] = None,
        ascending: typing.Optional[bool] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.List[Passage]:
        """
        Retrieve the memories in an agent's archival memory store (paginated query).

        Parameters
        ----------
        agent_id : str

        after : typing.Optional[str]
            Unique ID of the memory to start the query range at.

        before : typing.Optional[str]
            Unique ID of the memory to end the query range at.

        limit : typing.Optional[int]
            How many results to include in the response.

        search : typing.Optional[str]
            Search passages by text

        ascending : typing.Optional[bool]
            Whether to sort passages oldest to newest (True, default) or newest to oldest (False)

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

        Returns
        -------
        typing.List[Passage]
            Successful Response

        Examples
        --------
        import asyncio

        from letta_client import AsyncLetta

        client = AsyncLetta(
            project="YOUR_PROJECT",
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.agents.passages.list(
                agent_id="agent_id",
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.list(
            agent_id,
            after=after,
            before=before,
            limit=limit,
            search=search,
            ascending=ascending,
            request_options=request_options,
        )
        return _response.data

    async def create(
        self,
        agent_id: str,
        *,
        text: str,
        tags: typing.Optional[typing.Sequence[str]] = OMIT,
        created_at: typing.Optional[dt.datetime] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.List[Passage]:
        """
        Insert a memory into an agent's archival memory store.

        Parameters
        ----------
        agent_id : str

        text : str
            Text to write to archival memory.

        tags : typing.Optional[typing.Sequence[str]]
            Optional list of tags to attach to the memory.

        created_at : typing.Optional[dt.datetime]
            Optional timestamp for the memory (defaults to current UTC time).

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

        Returns
        -------
        typing.List[Passage]
            Successful Response

        Examples
        --------
        import asyncio

        from letta_client import AsyncLetta

        client = AsyncLetta(
            project="YOUR_PROJECT",
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.agents.passages.create(
                agent_id="agent_id",
                text="text",
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.create(
            agent_id, text=text, tags=tags, created_at=created_at, request_options=request_options
        )
        return _response.data

    async def search(
        self,
        agent_id: str,
        *,
        query: str,
        tags: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
        tag_match_mode: typing.Optional[PassagesSearchRequestTagMatchMode] = None,
        top_k: typing.Optional[int] = None,
        start_datetime: typing.Optional[dt.datetime] = None,
        end_datetime: typing.Optional[dt.datetime] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ArchivalMemorySearchResponse:
        """
        Search archival memory using semantic (embedding-based) search with optional temporal filtering.

        This endpoint allows manual triggering of archival memory searches, enabling users to query
        an agent's archival memory store directly via the API. The search uses the same functionality
        as the agent's archival_memory_search tool but is accessible for external API usage.

        Parameters
        ----------
        agent_id : str

        query : str
            String to search for using semantic similarity

        tags : typing.Optional[typing.Union[str, typing.Sequence[str]]]
            Optional list of tags to filter search results

        tag_match_mode : typing.Optional[PassagesSearchRequestTagMatchMode]
            How to match tags - 'any' to match passages with any of the tags, 'all' to match only passages with all tags

        top_k : typing.Optional[int]
            Maximum number of results to return. Uses system default if not specified

        start_datetime : typing.Optional[dt.datetime]
            Filter results to passages created after this datetime

        end_datetime : typing.Optional[dt.datetime]
            Filter results to passages created before this datetime

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

        Returns
        -------
        ArchivalMemorySearchResponse
            Successful Response

        Examples
        --------
        import asyncio

        from letta_client import AsyncLetta

        client = AsyncLetta(
            project="YOUR_PROJECT",
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.agents.passages.search(
                agent_id="agent_id",
                query="query",
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.search(
            agent_id,
            query=query,
            tags=tags,
            tag_match_mode=tag_match_mode,
            top_k=top_k,
            start_datetime=start_datetime,
            end_datetime=end_datetime,
            request_options=request_options,
        )
        return _response.data

    async def delete(
        self, agent_id: str, memory_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> typing.Optional[typing.Any]:
        """
        Delete a memory from an agent's archival memory store.

        Parameters
        ----------
        agent_id : str

        memory_id : str

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

        Returns
        -------
        typing.Optional[typing.Any]
            Successful Response

        Examples
        --------
        import asyncio

        from letta_client import AsyncLetta

        client = AsyncLetta(
            project="YOUR_PROJECT",
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.agents.passages.delete(
                agent_id="agent_id",
                memory_id="memory_id",
            )


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

    async def modify(
        self, agent_id: str, memory_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> None:
        """
        Parameters
        ----------
        agent_id : str

        memory_id : str

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

        Returns
        -------
        None

        Examples
        --------
        import asyncio

        from letta_client import AsyncLetta

        client = AsyncLetta(
            project="YOUR_PROJECT",
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.agents.passages.modify(
                agent_id="agent_id",
                memory_id="memory_id",
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.modify(agent_id, memory_id, request_options=request_options)
        return _response.data
