"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""

from .basesdk import BaseSDK
from .httpclient import AsyncHttpClient, ClientOwner, HttpClient, close_clients
from .sdkconfiguration import SDKConfiguration
from .utils.logger import Logger, get_default_logger
from .utils.retries import RetryConfig
import httpx
import importlib
from syllable_sdk import models, utils
from syllable_sdk._hooks import SDKHooks
from syllable_sdk.types import OptionalNullable, UNSET
import sys
from typing import Any, Callable, Dict, Optional, TYPE_CHECKING, Union, cast
import weakref

if TYPE_CHECKING:
    from syllable_sdk.agents import Agents
    from syllable_sdk.channels import Channels
    from syllable_sdk.conversations import Conversations
    from syllable_sdk.custom_messages import CustomMessages
    from syllable_sdk.dashboards import Dashboards
    from syllable_sdk.data_sources import DataSources
    from syllable_sdk.events import Events
    from syllable_sdk.incidents import Incidents
    from syllable_sdk.insights_sdk import InsightsSDK
    from syllable_sdk.language_groups import LanguageGroups
    from syllable_sdk.organizations import Organizations
    from syllable_sdk.outbound import Outbound
    from syllable_sdk.permissions import Permissions
    from syllable_sdk.prompts import Prompts
    from syllable_sdk.roles import Roles
    from syllable_sdk.services import Services
    from syllable_sdk.session_debug import SessionDebug
    from syllable_sdk.session_labels import SessionLabels
    from syllable_sdk.sessions import Sessions
    from syllable_sdk.takeouts import Takeouts
    from syllable_sdk.tools import Tools
    from syllable_sdk.users import Users
    from syllable_sdk.v1 import V1


class SyllableSDK(BaseSDK):
    r"""SyllableSDK:
    # Syllable Platform SDK

    Syllable SDK gives you the power of awesome AI agentry. 🚀

    ## Overview

    The Syllable SDK provides a comprehensive set of tools and APIs to integrate powerful AI
    capabilities into your communication applications. Whether you're building phone agents, chatbots,
    virtual assistants, or any other AI-driven solutions, Syllable SDK has got you covered.

    ## Features

    - **Agent Configuration**: Create and manage agents that can interact with users across various
    channels.
    - **Channel Management**: Configure channels like SMS, web chat, and more to connect agents with
    users.
    - **Custom Messages**: Set up custom messages that agents can deliver as greetings or responses.
    - **Conversations**: Track and manage conversations between users and agents, including session
    management.
    - **Tools and Workflows**: Leverage tools and workflows to enhance agent capabilities, such as data
    processing and API calls.
    - **Data Sources**: Integrate data sources to provide agents with additional context and
    information.
    - **Insights and Analytics**: Analyze conversations and sessions to gain insights into user
    interactions.
    - **Permissions and Security**: Manage permissions to control access to various features and
    functionalities.
    - **Language Support**: Define language groups to enable multilingual support for agents.
    - **Outbound Campaigns**: Create and manage outbound communication campaigns to reach users
    effectively.
    - **Session Labels**: Label sessions with evaluations of quality and descriptions of issues
    encountered.
    - **Incident Management**: Track and manage incidents related to agent interactions.

    """

    agents: "Agents"
    r"""Operations related to agent configuration. When a user interacts with the           Syllable system, they do so by communicating with an agent.           An agent is linked to a prompt, a custom message, and one or more channel targets to           define its behavior and capabilities. For more information, see           [Console docs](https://docs.syllable.ai/workspaces/Agents)."""
    channels: "Channels"
    r"""Operations related to channel configuration.           A channel is an organization-level point of communication, like a phone number or a web           chat. A channel can be associated with an agent by creating a channel target linking           them."""
    conversations: "Conversations"
    r"""Operations related to conversations.           A conversation is a record of messages between a user and an agent, and is composed of           one or more sessions."""
    data_sources: "DataSources"
    r"""Operations related to data sources. A data source is a blob of text that           can be made available to an agent's general info tools to provide more context to the           agent when generating its responses. For more information, see           [Console docs](https://docs.syllable.ai/Resources/DataSources)."""
    events: "Events"
    r"""Operations related to events. An event represents a specific occurrence           during a session. Currently the API/SDK only supports fetching logged events."""
    incidents: "Incidents"
    r"""Operations related to incidents."""
    insights: "InsightsSDK"
    r"""Operations related to insights results. An insight is a tool that processes          conversation data to extract information and generate reports."""
    custom_messages: "CustomMessages"
    r"""Operations related to custom message configuration.           A custom message is a pre-configured message delivered by an agent as a greeting at the           beginning of a conversation. Multiple agents can use the same custom mesasage. A custom           message has one or more rules defined, which allow for different messages to be           dynamically selected and delivered at runtime based on the current time and either           date or day of the week. For more information, see           [Console docs](https://docs.syllable.ai/Resources/Messages)."""
    permissions: "Permissions"
    r"""Operations related to permissions. A permission is a specific           capability or access level granted to a user within the Syllable system.           Permissions are used to control access to various features and functionalities."""
    prompts: "Prompts"
    r"""Operations related to prompts. A prompt defines the behavior of an           agent by delivering instructions to the LLM about how the agent should behave.           A prompt can be linked to one or more agents. A prompt can also be linked to tools to           allow an agent using the prompt to use them. For more information, see           [Console docs](https://docs.syllable.ai/Resources/Prompts)."""
    roles: "Roles"
    r"""Operations related to roles. A role is a collection of permissions           that can be assigned to users to control their access to various features within the           Syllable system."""
    services: "Services"
    r"""Operations related to service configuration. A service is a collection of           tools. You can specify an authentication method and values on a service, and any linked           tools will use that auth information to generate headers for HTTP calls."""
    session_labels: "SessionLabels"
    r"""Operations related to labeling sessions with evaluations of quality and           descriptions of issues the user encountered or other details. For more information, see           [Console docs](https://docs.syllable.ai/workspaces/Sessions)."""
    sessions: "Sessions"
    r"""Operations related to sessions. A session is a building block of a           conversation. For more information, see           [Console docs](https://docs.syllable.ai/workspaces/Sessions)."""
    session_debug: "SessionDebug"
    tools: "Tools"
    r"""Operations related to tool configuration. A tool is a function that an           agent can call to perform actions like accessing databases, making API calls, or           processing data. For an agent to have access to a tool, the prompt associated with that           agent should be linked to the tool and include instructions to use it. For more           information, see [Console docs](https://docs.syllable.ai/Resources/Tools)."""
    dashboards: "Dashboards"
    r"""Operations related to dashboards. Currently the API/SDK           only supports fetching basic information about dashboards."""
    organizations: "Organizations"
    r"""Operations related to organizations."""
    outbound: "Outbound"
    language_groups: "LanguageGroups"
    r"""Operations related to language groups. A language group is a           collection of language, voice, and DTMF configuration that can be linked to an agent to           define the languages and voices it supports. For more information, see           [Console docs](https://docs.syllable.ai/Resources/LanguageGroups)."""
    takeouts: "Takeouts"
    users: "Users"
    v1: "V1"
    _sub_sdk_map = {
        "agents": ("syllable_sdk.agents", "Agents"),
        "channels": ("syllable_sdk.channels", "Channels"),
        "conversations": ("syllable_sdk.conversations", "Conversations"),
        "data_sources": ("syllable_sdk.data_sources", "DataSources"),
        "events": ("syllable_sdk.events", "Events"),
        "incidents": ("syllable_sdk.incidents", "Incidents"),
        "insights": ("syllable_sdk.insights_sdk", "InsightsSDK"),
        "custom_messages": ("syllable_sdk.custom_messages", "CustomMessages"),
        "permissions": ("syllable_sdk.permissions", "Permissions"),
        "prompts": ("syllable_sdk.prompts", "Prompts"),
        "roles": ("syllable_sdk.roles", "Roles"),
        "services": ("syllable_sdk.services", "Services"),
        "session_labels": ("syllable_sdk.session_labels", "SessionLabels"),
        "sessions": ("syllable_sdk.sessions", "Sessions"),
        "session_debug": ("syllable_sdk.session_debug", "SessionDebug"),
        "tools": ("syllable_sdk.tools", "Tools"),
        "dashboards": ("syllable_sdk.dashboards", "Dashboards"),
        "organizations": ("syllable_sdk.organizations", "Organizations"),
        "outbound": ("syllable_sdk.outbound", "Outbound"),
        "language_groups": ("syllable_sdk.language_groups", "LanguageGroups"),
        "takeouts": ("syllable_sdk.takeouts", "Takeouts"),
        "users": ("syllable_sdk.users", "Users"),
        "v1": ("syllable_sdk.v1", "V1"),
    }

    def __init__(
        self,
        api_key_header: Optional[
            Union[Optional[str], Callable[[], Optional[str]]]
        ] = None,
        server_idx: Optional[int] = None,
        server_url: Optional[str] = None,
        url_params: Optional[Dict[str, str]] = None,
        client: Optional[HttpClient] = None,
        async_client: Optional[AsyncHttpClient] = None,
        retry_config: OptionalNullable[RetryConfig] = UNSET,
        timeout_ms: Optional[int] = None,
        debug_logger: Optional[Logger] = None,
    ) -> None:
        r"""Instantiates the SDK configuring it with the provided parameters.

        :param api_key_header: The api_key_header required for authentication
        :param server_idx: The index of the server to use for all methods
        :param server_url: The server URL to use for all methods
        :param url_params: Parameters to optionally template the server URL with
        :param client: The HTTP client to use for all synchronous methods
        :param async_client: The Async HTTP client to use for all asynchronous methods
        :param retry_config: The retry configuration to use for all supported methods
        :param timeout_ms: Optional request timeout applied to each operation in milliseconds
        """
        client_supplied = True
        if client is None:
            client = httpx.Client()
            client_supplied = False

        assert issubclass(
            type(client), HttpClient
        ), "The provided client must implement the HttpClient protocol."

        async_client_supplied = True
        if async_client is None:
            async_client = httpx.AsyncClient()
            async_client_supplied = False

        if debug_logger is None:
            debug_logger = get_default_logger()

        assert issubclass(
            type(async_client), AsyncHttpClient
        ), "The provided async_client must implement the AsyncHttpClient protocol."

        security: Any = None
        if callable(api_key_header):
            # pylint: disable=unnecessary-lambda-assignment
            security = lambda: models.Security(api_key_header=api_key_header())
        else:
            security = models.Security(api_key_header=api_key_header)

        if server_url is not None:
            if url_params is not None:
                server_url = utils.template_url(server_url, url_params)

        BaseSDK.__init__(
            self,
            SDKConfiguration(
                client=client,
                client_supplied=client_supplied,
                async_client=async_client,
                async_client_supplied=async_client_supplied,
                security=security,
                server_url=server_url,
                server_idx=server_idx,
                retry_config=retry_config,
                timeout_ms=timeout_ms,
                debug_logger=debug_logger,
            ),
            parent_ref=self,
        )

        hooks = SDKHooks()

        # pylint: disable=protected-access
        self.sdk_configuration.__dict__["_hooks"] = hooks

        current_server_url, *_ = self.sdk_configuration.get_server_details()
        server_url, self.sdk_configuration.client = hooks.sdk_init(
            current_server_url, client
        )
        if current_server_url != server_url:
            self.sdk_configuration.server_url = server_url

        weakref.finalize(
            self,
            close_clients,
            cast(ClientOwner, self.sdk_configuration),
            self.sdk_configuration.client,
            self.sdk_configuration.client_supplied,
            self.sdk_configuration.async_client,
            self.sdk_configuration.async_client_supplied,
        )

    def dynamic_import(self, modname, retries=3):
        for attempt in range(retries):
            try:
                return importlib.import_module(modname)
            except KeyError:
                # Clear any half-initialized module and retry
                sys.modules.pop(modname, None)
                if attempt == retries - 1:
                    break
        raise KeyError(f"Failed to import module '{modname}' after {retries} attempts")

    def __getattr__(self, name: str):
        if name in self._sub_sdk_map:
            module_path, class_name = self._sub_sdk_map[name]
            try:
                module = self.dynamic_import(module_path)
                klass = getattr(module, class_name)
                instance = klass(self.sdk_configuration, parent_ref=self)
                setattr(self, name, instance)
                return instance
            except ImportError as e:
                raise AttributeError(
                    f"Failed to import module {module_path} for attribute {name}: {e}"
                ) from e
            except AttributeError as e:
                raise AttributeError(
                    f"Failed to find class {class_name} in module {module_path} for attribute {name}: {e}"
                ) from e

        raise AttributeError(
            f"'{type(self).__name__}' object has no attribute '{name}'"
        )

    def __dir__(self):
        default_attrs = list(super().__dir__())
        lazy_attrs = list(self._sub_sdk_map.keys())
        return sorted(list(set(default_attrs + lazy_attrs)))

    def __enter__(self):
        return self

    async def __aenter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        if (
            self.sdk_configuration.client is not None
            and not self.sdk_configuration.client_supplied
        ):
            self.sdk_configuration.client.close()
        self.sdk_configuration.client = None

    async def __aexit__(self, exc_type, exc_val, exc_tb):
        if (
            self.sdk_configuration.async_client is not None
            and not self.sdk_configuration.async_client_supplied
        ):
            await self.sdk_configuration.async_client.aclose()
        self.sdk_configuration.async_client = None
