# 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 ..types.delete_all_threads_response import DeleteAllThreadsResponse
from ..types.message_input import MessageInput
from ..types.pin_thread_response import PinThreadResponse
from ..types.thread_list_response import ThreadListResponse
from ..types.thread_response import ThreadResponse
from .raw_client import AsyncRawThreadsClient, RawThreadsClient

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


class ThreadsClient:
    def __init__(self, *, client_wrapper: SyncClientWrapper):
        self._raw_client = RawThreadsClient(client_wrapper=client_wrapper)

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

        Returns
        -------
        RawThreadsClient
        """
        return self._raw_client

    def list_threads(
        self,
        *,
        organization_id: typing.Optional[str] = None,
        limit: typing.Optional[int] = None,
        order: typing.Optional[str] = None,
        after: typing.Optional[str] = None,
        before: typing.Optional[str] = None,
        assistant_id: typing.Optional[str] = None,
        workflow_id: typing.Optional[str] = None,
        visible_in_ui: typing.Optional[bool] = None,
        include_deleted: typing.Optional[bool] = None,
        is_pinned: typing.Optional[bool] = None,
        include_total: typing.Optional[bool] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ThreadListResponse:
        """
        List threads for the authenticated user with cursor-based pagination.

        Supports both authentication methods:
        - Bearer token: Use Authorization header with user token
        - API key: Use X-API-Key header with organization API key

        Optimized for infinite scroll UIs (like ChatGPT/Claude sidebar):
        - Use 'after' cursor to load more threads as user scrolls down
        - Pinned threads always appear first (only on initial load)
        - Set 'visible_in_ui=true' (default) to show only UI-visible threads
        - Set 'include_total=false' (default) for best performance (~50% faster)

        If organization_id is provided, returns threads from that organization only.
        If organization_id is not provided, returns all threads from all organizations the user belongs to.

        Cursor-based pagination:
        - Use 'after' to get threads after a specific thread (for next page / infinite scroll)
        - Use 'before' to get threads before a specific thread (for previous page)
        - The 'last_id' in the response should be used as the 'after' cursor for infinite scroll
        - The 'first_id' in the response should be used as the 'before' cursor

        Infinite scroll example:
        1. Initial load: GET /v1/threads?limit=20&order=desc
        2. User scrolls down: GET /v1/threads?after={last_id}&limit=20&order=desc
        3. Repeat step 2 while has_more=true

        Performance tips:
        - Keep limit between 20-30 for optimal mobile performance
        - Use include_total=false (default) to avoid expensive COUNT query
        - Pinned threads appear only on first page, not in subsequent pagination

        Parameters
        ----------
        organization_id : typing.Optional[str]
            Organization ID to filter by (optional)

        limit : typing.Optional[int]
            Number of threads per page. Recommended: 20-30 for optimal performance.

        order : typing.Optional[str]
            Sort order by last activity. 'desc' = newest first, 'asc' = oldest first. Note: Pinned threads always appear first regardless of order.

        after : typing.Optional[str]
            Cursor for pagination. Returns threads after this thread ID. Use 'last_id' from previous response for infinite scroll.

        before : typing.Optional[str]
            Cursor for pagination. Returns threads before this thread ID. Not typically needed for infinite scroll (use 'after' instead).

        assistant_id : typing.Optional[str]
            Filter by assistant ID

        workflow_id : typing.Optional[str]
            Filter by workflow ID (FlowPlate integration)

        visible_in_ui : typing.Optional[bool]
            Filter by UI visibility. None returns all threads, True returns only visible threads, False returns only hidden threads

        include_deleted : typing.Optional[bool]
            Include deleted threads

        is_pinned : typing.Optional[bool]
            Filter by pinned status. None (default) returns all threads with pinned first. True returns only pinned, False returns only unpinned. Not recommended for sidebar infinite scroll.

        include_total : typing.Optional[bool]
            Include total count of matching threads. Adds latency due to COUNT query. Not needed for infinite scroll.

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

        Returns
        -------
        ThreadListResponse
            Successful Response

        Examples
        --------
        from aitronos import Aitronos

        client = Aitronos(
            api_key="YOUR_API_KEY",
            token="YOUR_TOKEN",
        )
        client.threads.list_threads()
        """
        _response = self._raw_client.list_threads(
            organization_id=organization_id,
            limit=limit,
            order=order,
            after=after,
            before=before,
            assistant_id=assistant_id,
            workflow_id=workflow_id,
            visible_in_ui=visible_in_ui,
            include_deleted=include_deleted,
            is_pinned=is_pinned,
            include_total=include_total,
            request_options=request_options,
        )
        return _response.data

    def create_thread(
        self,
        *,
        organization_id: str,
        title: typing.Optional[str] = OMIT,
        metadata: typing.Optional[typing.Dict[str, typing.Any]] = OMIT,
        assistant_id: typing.Optional[str] = OMIT,
        visible_in_ui: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ThreadResponse:
        """
        Create a new thread.

        Supports both authentication methods:
        - Bearer token: Use Authorization header with user token
        - API key: Use X-API-Key header with organization API key

        The authenticated user will be set as the creator.
        Organization membership is verified before creation.

        Parameters
        ----------
        organization_id : str
            Organization ID

        title : typing.Optional[str]
            Thread title

        metadata : typing.Optional[typing.Dict[str, typing.Any]]
            Custom key-value pairs (max 16 pairs, keys ≤64 chars, values ≤512 chars)

        assistant_id : typing.Optional[str]
            Assistant ID to bind

        visible_in_ui : typing.Optional[bool]
            Whether this thread should be visible in the user interface

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

        Returns
        -------
        ThreadResponse
            Successful Response

        Examples
        --------
        from aitronos import Aitronos

        client = Aitronos(
            api_key="YOUR_API_KEY",
            token="YOUR_TOKEN",
        )
        client.threads.create_thread(
            organization_id="organization_id",
        )
        """
        _response = self._raw_client.create_thread(
            organization_id=organization_id,
            title=title,
            metadata=metadata,
            assistant_id=assistant_id,
            visible_in_ui=visible_in_ui,
            request_options=request_options,
        )
        return _response.data

    def delete_all_threads(
        self, *, organization_id: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None
    ) -> DeleteAllThreadsResponse:
        """
        Delete all threads for the authenticated user.

        Supports both authentication methods:
        - Bearer token: Use Authorization header with user token
        - API key: Use X-API-Key header with organization API key

        If organization_id is provided, only threads within that organization are deleted.
        If omitted, all threads across all organizations are deleted.

        Parameters
        ----------
        organization_id : typing.Optional[str]
            Scope deletion to a specific organization. If omitted, deletes all threads across all organizations.

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

        Returns
        -------
        DeleteAllThreadsResponse
            Successful Response

        Examples
        --------
        from aitronos import Aitronos

        client = Aitronos(
            api_key="YOUR_API_KEY",
            token="YOUR_TOKEN",
        )
        client.threads.delete_all_threads()
        """
        _response = self._raw_client.delete_all_threads(
            organization_id=organization_id, request_options=request_options
        )
        return _response.data

    def get_thread(self, thread_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> ThreadResponse:
        """
        Get a single thread by ID.

        Supports both authentication methods:
        - Bearer token: Use Authorization header with user token
        - API key: Use X-API-Key header with organization API key

        User must be the creator of the thread to access it.

        Parameters
        ----------
        thread_id : str

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

        Returns
        -------
        ThreadResponse
            Successful Response

        Examples
        --------
        from aitronos import Aitronos

        client = Aitronos(
            api_key="YOUR_API_KEY",
            token="YOUR_TOKEN",
        )
        client.threads.get_thread(
            thread_id="thread_id",
        )
        """
        _response = self._raw_client.get_thread(thread_id, request_options=request_options)
        return _response.data

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

        Supports both authentication methods:
        - Bearer token: Use Authorization header with user token
        - API key: Use X-API-Key header with organization API key

        Only the thread creator can delete it.

        Parameters
        ----------
        thread_id : str

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

        Returns
        -------
        None

        Examples
        --------
        from aitronos import Aitronos

        client = Aitronos(
            api_key="YOUR_API_KEY",
            token="YOUR_TOKEN",
        )
        client.threads.delete_thread(
            thread_id="thread_id",
        )
        """
        _response = self._raw_client.delete_thread(thread_id, request_options=request_options)
        return _response.data

    def update_thread(
        self,
        thread_id: str,
        *,
        title: typing.Optional[str] = OMIT,
        metadata: typing.Optional[typing.Dict[str, typing.Any]] = OMIT,
        assistant_id: typing.Optional[str] = OMIT,
        visible_in_ui: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ThreadResponse:
        """
        Update a thread's title, metadata, or visibility.

        Supports both authentication methods:
        - Bearer token: Use Authorization header with user token
        - API key: Use X-API-Key header with organization API key

        Only the thread creator can update it.

        Note: assistant_id cannot be changed once a thread has messages.
        The assistant binding is locked after the first message to ensure
        conversation consistency.

        Parameters
        ----------
        thread_id : str

        title : typing.Optional[str]
            Thread title

        metadata : typing.Optional[typing.Dict[str, typing.Any]]
            Custom key-value pairs (max 16 pairs, keys ≤64 chars, values ≤512 chars)

        assistant_id : typing.Optional[str]
            Assistant ID to bind

        visible_in_ui : typing.Optional[bool]
            Whether this thread should be visible in the user interface

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

        Returns
        -------
        ThreadResponse
            Successful Response

        Examples
        --------
        from aitronos import Aitronos

        client = Aitronos(
            api_key="YOUR_API_KEY",
            token="YOUR_TOKEN",
        )
        client.threads.update_thread(
            thread_id="thread_id",
        )
        """
        _response = self._raw_client.update_thread(
            thread_id,
            title=title,
            metadata=metadata,
            assistant_id=assistant_id,
            visible_in_ui=visible_in_ui,
            request_options=request_options,
        )
        return _response.data

    def pin_thread(
        self, thread_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> PinThreadResponse:
        """
        Pin a thread to keep it at the top of the thread list.

        Supports both authentication methods:
        - Bearer token: Use Authorization header with user token
        - API key: Use X-API-Key header with organization API key

        Only the thread creator can pin it.
        Maximum 20 pinned threads per user per organization.

        Pinned threads appear first in list results, sorted by pin time (most recently pinned first).

        Parameters
        ----------
        thread_id : str

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

        Returns
        -------
        PinThreadResponse
            Successful Response

        Examples
        --------
        from aitronos import Aitronos

        client = Aitronos(
            api_key="YOUR_API_KEY",
            token="YOUR_TOKEN",
        )
        client.threads.pin_thread(
            thread_id="thread_id",
        )
        """
        _response = self._raw_client.pin_thread(thread_id, request_options=request_options)
        return _response.data

    def unpin_thread(
        self, thread_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> PinThreadResponse:
        """
        Unpin a thread to remove it from the top of the thread list.

        Supports both authentication methods:
        - Bearer token: Use Authorization header with user token
        - API key: Use X-API-Key header with organization API key

        Only the thread creator can unpin it.

        Parameters
        ----------
        thread_id : str

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

        Returns
        -------
        PinThreadResponse
            Successful Response

        Examples
        --------
        from aitronos import Aitronos

        client = Aitronos(
            api_key="YOUR_API_KEY",
            token="YOUR_TOKEN",
        )
        client.threads.unpin_thread(
            thread_id="thread_id",
        )
        """
        _response = self._raw_client.unpin_thread(thread_id, request_options=request_options)
        return _response.data

    def generate_thread_name(
        self,
        thread_id: str,
        *,
        stream: typing.Optional[bool] = None,
        messages: typing.Optional[typing.Sequence[MessageInput]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.Any:
        """
        Generate AI-powered thread name.

        Supports both authentication methods:
        - Bearer token: Use Authorization header with user token
        - API key: Use X-API-Key header with organization API key

        Analyzes conversation content and generates a concise, descriptive title.
        Can accept messages in request body for real-time scenarios or fetch from database.

        Supports streaming mode for real-time title generation feedback.

        Performance optimizations:
        - Target: < 3 seconds for 95th percentile
        - Single optimized query for thread verification (indexed on thread_id)
        - Zero DB latency when messages provided in request body
        - Async operations throughout (non-blocking)
        - Connection pooling for HTTP client
        - Fast model (ftg-3.0-speed) for < 2s generation
        - Single UPDATE query with RETURNING for title update
        - Comprehensive timing logs for monitoring

        Parameters
        ----------
        thread_id : str

        stream : typing.Optional[bool]
            Enable streaming mode

        messages : typing.Optional[typing.Sequence[MessageInput]]
            Optional messages to use for name generation

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

        Returns
        -------
        typing.Any
            Successful Response

        Examples
        --------
        from aitronos import Aitronos

        client = Aitronos(
            api_key="YOUR_API_KEY",
            token="YOUR_TOKEN",
        )
        client.threads.generate_thread_name(
            thread_id="thread_id",
        )
        """
        _response = self._raw_client.generate_thread_name(
            thread_id, stream=stream, messages=messages, request_options=request_options
        )
        return _response.data


class AsyncThreadsClient:
    def __init__(self, *, client_wrapper: AsyncClientWrapper):
        self._raw_client = AsyncRawThreadsClient(client_wrapper=client_wrapper)

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

        Returns
        -------
        AsyncRawThreadsClient
        """
        return self._raw_client

    async def list_threads(
        self,
        *,
        organization_id: typing.Optional[str] = None,
        limit: typing.Optional[int] = None,
        order: typing.Optional[str] = None,
        after: typing.Optional[str] = None,
        before: typing.Optional[str] = None,
        assistant_id: typing.Optional[str] = None,
        workflow_id: typing.Optional[str] = None,
        visible_in_ui: typing.Optional[bool] = None,
        include_deleted: typing.Optional[bool] = None,
        is_pinned: typing.Optional[bool] = None,
        include_total: typing.Optional[bool] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ThreadListResponse:
        """
        List threads for the authenticated user with cursor-based pagination.

        Supports both authentication methods:
        - Bearer token: Use Authorization header with user token
        - API key: Use X-API-Key header with organization API key

        Optimized for infinite scroll UIs (like ChatGPT/Claude sidebar):
        - Use 'after' cursor to load more threads as user scrolls down
        - Pinned threads always appear first (only on initial load)
        - Set 'visible_in_ui=true' (default) to show only UI-visible threads
        - Set 'include_total=false' (default) for best performance (~50% faster)

        If organization_id is provided, returns threads from that organization only.
        If organization_id is not provided, returns all threads from all organizations the user belongs to.

        Cursor-based pagination:
        - Use 'after' to get threads after a specific thread (for next page / infinite scroll)
        - Use 'before' to get threads before a specific thread (for previous page)
        - The 'last_id' in the response should be used as the 'after' cursor for infinite scroll
        - The 'first_id' in the response should be used as the 'before' cursor

        Infinite scroll example:
        1. Initial load: GET /v1/threads?limit=20&order=desc
        2. User scrolls down: GET /v1/threads?after={last_id}&limit=20&order=desc
        3. Repeat step 2 while has_more=true

        Performance tips:
        - Keep limit between 20-30 for optimal mobile performance
        - Use include_total=false (default) to avoid expensive COUNT query
        - Pinned threads appear only on first page, not in subsequent pagination

        Parameters
        ----------
        organization_id : typing.Optional[str]
            Organization ID to filter by (optional)

        limit : typing.Optional[int]
            Number of threads per page. Recommended: 20-30 for optimal performance.

        order : typing.Optional[str]
            Sort order by last activity. 'desc' = newest first, 'asc' = oldest first. Note: Pinned threads always appear first regardless of order.

        after : typing.Optional[str]
            Cursor for pagination. Returns threads after this thread ID. Use 'last_id' from previous response for infinite scroll.

        before : typing.Optional[str]
            Cursor for pagination. Returns threads before this thread ID. Not typically needed for infinite scroll (use 'after' instead).

        assistant_id : typing.Optional[str]
            Filter by assistant ID

        workflow_id : typing.Optional[str]
            Filter by workflow ID (FlowPlate integration)

        visible_in_ui : typing.Optional[bool]
            Filter by UI visibility. None returns all threads, True returns only visible threads, False returns only hidden threads

        include_deleted : typing.Optional[bool]
            Include deleted threads

        is_pinned : typing.Optional[bool]
            Filter by pinned status. None (default) returns all threads with pinned first. True returns only pinned, False returns only unpinned. Not recommended for sidebar infinite scroll.

        include_total : typing.Optional[bool]
            Include total count of matching threads. Adds latency due to COUNT query. Not needed for infinite scroll.

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

        Returns
        -------
        ThreadListResponse
            Successful Response

        Examples
        --------
        import asyncio

        from aitronos import AsyncAitronos

        client = AsyncAitronos(
            api_key="YOUR_API_KEY",
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.threads.list_threads()


        asyncio.run(main())
        """
        _response = await self._raw_client.list_threads(
            organization_id=organization_id,
            limit=limit,
            order=order,
            after=after,
            before=before,
            assistant_id=assistant_id,
            workflow_id=workflow_id,
            visible_in_ui=visible_in_ui,
            include_deleted=include_deleted,
            is_pinned=is_pinned,
            include_total=include_total,
            request_options=request_options,
        )
        return _response.data

    async def create_thread(
        self,
        *,
        organization_id: str,
        title: typing.Optional[str] = OMIT,
        metadata: typing.Optional[typing.Dict[str, typing.Any]] = OMIT,
        assistant_id: typing.Optional[str] = OMIT,
        visible_in_ui: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ThreadResponse:
        """
        Create a new thread.

        Supports both authentication methods:
        - Bearer token: Use Authorization header with user token
        - API key: Use X-API-Key header with organization API key

        The authenticated user will be set as the creator.
        Organization membership is verified before creation.

        Parameters
        ----------
        organization_id : str
            Organization ID

        title : typing.Optional[str]
            Thread title

        metadata : typing.Optional[typing.Dict[str, typing.Any]]
            Custom key-value pairs (max 16 pairs, keys ≤64 chars, values ≤512 chars)

        assistant_id : typing.Optional[str]
            Assistant ID to bind

        visible_in_ui : typing.Optional[bool]
            Whether this thread should be visible in the user interface

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

        Returns
        -------
        ThreadResponse
            Successful Response

        Examples
        --------
        import asyncio

        from aitronos import AsyncAitronos

        client = AsyncAitronos(
            api_key="YOUR_API_KEY",
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.threads.create_thread(
                organization_id="organization_id",
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.create_thread(
            organization_id=organization_id,
            title=title,
            metadata=metadata,
            assistant_id=assistant_id,
            visible_in_ui=visible_in_ui,
            request_options=request_options,
        )
        return _response.data

    async def delete_all_threads(
        self, *, organization_id: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None
    ) -> DeleteAllThreadsResponse:
        """
        Delete all threads for the authenticated user.

        Supports both authentication methods:
        - Bearer token: Use Authorization header with user token
        - API key: Use X-API-Key header with organization API key

        If organization_id is provided, only threads within that organization are deleted.
        If omitted, all threads across all organizations are deleted.

        Parameters
        ----------
        organization_id : typing.Optional[str]
            Scope deletion to a specific organization. If omitted, deletes all threads across all organizations.

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

        Returns
        -------
        DeleteAllThreadsResponse
            Successful Response

        Examples
        --------
        import asyncio

        from aitronos import AsyncAitronos

        client = AsyncAitronos(
            api_key="YOUR_API_KEY",
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.threads.delete_all_threads()


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

    async def get_thread(
        self, thread_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> ThreadResponse:
        """
        Get a single thread by ID.

        Supports both authentication methods:
        - Bearer token: Use Authorization header with user token
        - API key: Use X-API-Key header with organization API key

        User must be the creator of the thread to access it.

        Parameters
        ----------
        thread_id : str

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

        Returns
        -------
        ThreadResponse
            Successful Response

        Examples
        --------
        import asyncio

        from aitronos import AsyncAitronos

        client = AsyncAitronos(
            api_key="YOUR_API_KEY",
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.threads.get_thread(
                thread_id="thread_id",
            )


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

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

        Supports both authentication methods:
        - Bearer token: Use Authorization header with user token
        - API key: Use X-API-Key header with organization API key

        Only the thread creator can delete it.

        Parameters
        ----------
        thread_id : str

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

        Returns
        -------
        None

        Examples
        --------
        import asyncio

        from aitronos import AsyncAitronos

        client = AsyncAitronos(
            api_key="YOUR_API_KEY",
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.threads.delete_thread(
                thread_id="thread_id",
            )


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

    async def update_thread(
        self,
        thread_id: str,
        *,
        title: typing.Optional[str] = OMIT,
        metadata: typing.Optional[typing.Dict[str, typing.Any]] = OMIT,
        assistant_id: typing.Optional[str] = OMIT,
        visible_in_ui: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ThreadResponse:
        """
        Update a thread's title, metadata, or visibility.

        Supports both authentication methods:
        - Bearer token: Use Authorization header with user token
        - API key: Use X-API-Key header with organization API key

        Only the thread creator can update it.

        Note: assistant_id cannot be changed once a thread has messages.
        The assistant binding is locked after the first message to ensure
        conversation consistency.

        Parameters
        ----------
        thread_id : str

        title : typing.Optional[str]
            Thread title

        metadata : typing.Optional[typing.Dict[str, typing.Any]]
            Custom key-value pairs (max 16 pairs, keys ≤64 chars, values ≤512 chars)

        assistant_id : typing.Optional[str]
            Assistant ID to bind

        visible_in_ui : typing.Optional[bool]
            Whether this thread should be visible in the user interface

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

        Returns
        -------
        ThreadResponse
            Successful Response

        Examples
        --------
        import asyncio

        from aitronos import AsyncAitronos

        client = AsyncAitronos(
            api_key="YOUR_API_KEY",
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.threads.update_thread(
                thread_id="thread_id",
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.update_thread(
            thread_id,
            title=title,
            metadata=metadata,
            assistant_id=assistant_id,
            visible_in_ui=visible_in_ui,
            request_options=request_options,
        )
        return _response.data

    async def pin_thread(
        self, thread_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> PinThreadResponse:
        """
        Pin a thread to keep it at the top of the thread list.

        Supports both authentication methods:
        - Bearer token: Use Authorization header with user token
        - API key: Use X-API-Key header with organization API key

        Only the thread creator can pin it.
        Maximum 20 pinned threads per user per organization.

        Pinned threads appear first in list results, sorted by pin time (most recently pinned first).

        Parameters
        ----------
        thread_id : str

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

        Returns
        -------
        PinThreadResponse
            Successful Response

        Examples
        --------
        import asyncio

        from aitronos import AsyncAitronos

        client = AsyncAitronos(
            api_key="YOUR_API_KEY",
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.threads.pin_thread(
                thread_id="thread_id",
            )


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

    async def unpin_thread(
        self, thread_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> PinThreadResponse:
        """
        Unpin a thread to remove it from the top of the thread list.

        Supports both authentication methods:
        - Bearer token: Use Authorization header with user token
        - API key: Use X-API-Key header with organization API key

        Only the thread creator can unpin it.

        Parameters
        ----------
        thread_id : str

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

        Returns
        -------
        PinThreadResponse
            Successful Response

        Examples
        --------
        import asyncio

        from aitronos import AsyncAitronos

        client = AsyncAitronos(
            api_key="YOUR_API_KEY",
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.threads.unpin_thread(
                thread_id="thread_id",
            )


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

    async def generate_thread_name(
        self,
        thread_id: str,
        *,
        stream: typing.Optional[bool] = None,
        messages: typing.Optional[typing.Sequence[MessageInput]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.Any:
        """
        Generate AI-powered thread name.

        Supports both authentication methods:
        - Bearer token: Use Authorization header with user token
        - API key: Use X-API-Key header with organization API key

        Analyzes conversation content and generates a concise, descriptive title.
        Can accept messages in request body for real-time scenarios or fetch from database.

        Supports streaming mode for real-time title generation feedback.

        Performance optimizations:
        - Target: < 3 seconds for 95th percentile
        - Single optimized query for thread verification (indexed on thread_id)
        - Zero DB latency when messages provided in request body
        - Async operations throughout (non-blocking)
        - Connection pooling for HTTP client
        - Fast model (ftg-3.0-speed) for < 2s generation
        - Single UPDATE query with RETURNING for title update
        - Comprehensive timing logs for monitoring

        Parameters
        ----------
        thread_id : str

        stream : typing.Optional[bool]
            Enable streaming mode

        messages : typing.Optional[typing.Sequence[MessageInput]]
            Optional messages to use for name generation

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

        Returns
        -------
        typing.Any
            Successful Response

        Examples
        --------
        import asyncio

        from aitronos import AsyncAitronos

        client = AsyncAitronos(
            api_key="YOUR_API_KEY",
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.threads.generate_thread_name(
                thread_id="thread_id",
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.generate_thread_name(
            thread_id, stream=stream, messages=messages, request_options=request_options
        )
        return _response.data
