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

import typing
from ..core.client_wrapper import SyncClientWrapper
from ..types.input import Input
from ..types.runnable_config import RunnableConfig
from ..core.request_options import RequestOptions
from ..core.serialization import convert_and_respect_annotation_metadata
from ..core.pydantic_utilities import parse_obj_as
from ..errors.unprocessable_entity_error import UnprocessableEntityError
from ..types.http_validation_error import HttpValidationError
from json.decoder import JSONDecodeError
from ..core.api_error import ApiError
import httpx_sse
import json
from .types.score import Score
from .types.value import Value
from ..core.client_wrapper import AsyncClientWrapper

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


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

    def create_run(
        self,
        *,
        thread_id: str,
        input: typing.Optional[Input] = OMIT,
        config: typing.Optional[RunnableConfig] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.Optional[typing.Any]:
        """
        Create a run.

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

        input : typing.Optional[Input]

        config : typing.Optional[RunnableConfig]

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

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

        Examples
        --------
        from akili import AkiliApi

        client = AkiliApi(
            token="YOUR_TOKEN",
        )
        client.runs.create_run(
            thread_id="thread_id",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            "runs",
            method="POST",
            json={
                "thread_id": thread_id,
                "input": convert_and_respect_annotation_metadata(object_=input, annotation=Input, direction="write"),
                "config": convert_and_respect_annotation_metadata(
                    object_=config, annotation=RunnableConfig, direction="write"
                ),
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    typing.Optional[typing.Any],
                    parse_obj_as(
                        type_=typing.Optional[typing.Any],  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    typing.cast(
                        HttpValidationError,
                        parse_obj_as(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def stream_run(
        self,
        *,
        thread_id: str,
        input: typing.Optional[Input] = OMIT,
        config: typing.Optional[RunnableConfig] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.Iterator[typing.Optional[typing.Any]]:
        """
        Create a run.

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

        input : typing.Optional[Input]

        config : typing.Optional[RunnableConfig]

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

        Yields
        ------
        typing.Iterator[typing.Optional[typing.Any]]
            Successful Response

        Examples
        --------
        from akili import AkiliApi

        client = AkiliApi(
            token="YOUR_TOKEN",
        )
        response = client.runs.stream_run(
            thread_id="thread_id",
        )
        for chunk in response:
            yield chunk
        """
        with self._client_wrapper.httpx_client.stream(
            "runs/stream",
            method="POST",
            json={
                "thread_id": thread_id,
                "input": convert_and_respect_annotation_metadata(object_=input, annotation=Input, direction="write"),
                "config": convert_and_respect_annotation_metadata(
                    object_=config, annotation=RunnableConfig, direction="write"
                ),
            },
            request_options=request_options,
            omit=OMIT,
        ) as _response:
            try:
                if 200 <= _response.status_code < 300:
                    _event_source = httpx_sse.EventSource(_response)
                    for _sse in _event_source.iter_sse():
                        try:
                            yield typing.cast(
                                typing.Optional[typing.Any],
                                parse_obj_as(
                                    type_=typing.Optional[typing.Any],  # type: ignore
                                    object_=json.loads(_sse.data),
                                ),
                            )
                        except:
                            pass
                    return
                _response.read()
                if _response.status_code == 422:
                    raise UnprocessableEntityError(
                        typing.cast(
                            HttpValidationError,
                            parse_obj_as(
                                type_=HttpValidationError,  # type: ignore
                                object_=_response.json(),
                            ),
                        )
                    )
                _response_json = _response.json()
            except JSONDecodeError:
                raise ApiError(status_code=_response.status_code, body=_response.text)
            raise ApiError(status_code=_response.status_code, body=_response_json)

    def input_schema(
        self, *, request_options: typing.Optional[RequestOptions] = None
    ) -> typing.Dict[str, typing.Optional[typing.Any]]:
        """
        Return the input schema of the runnable.

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

        Returns
        -------
        typing.Dict[str, typing.Optional[typing.Any]]
            Successful Response

        Examples
        --------
        from akili import AkiliApi

        client = AkiliApi(
            token="YOUR_TOKEN",
        )
        client.runs.input_schema()
        """
        _response = self._client_wrapper.httpx_client.request(
            "runs/input_schema",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    typing.Dict[str, typing.Optional[typing.Any]],
                    parse_obj_as(
                        type_=typing.Dict[str, typing.Optional[typing.Any]],  # type: ignore
                        object_=_response.json(),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def output_schema(
        self, *, request_options: typing.Optional[RequestOptions] = None
    ) -> typing.Dict[str, typing.Optional[typing.Any]]:
        """
        Return the output schema of the runnable.

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

        Returns
        -------
        typing.Dict[str, typing.Optional[typing.Any]]
            Successful Response

        Examples
        --------
        from akili import AkiliApi

        client = AkiliApi(
            token="YOUR_TOKEN",
        )
        client.runs.output_schema()
        """
        _response = self._client_wrapper.httpx_client.request(
            "runs/output_schema",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    typing.Dict[str, typing.Optional[typing.Any]],
                    parse_obj_as(
                        type_=typing.Dict[str, typing.Optional[typing.Any]],  # type: ignore
                        object_=_response.json(),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def config_schema(
        self, *, request_options: typing.Optional[RequestOptions] = None
    ) -> typing.Dict[str, typing.Optional[typing.Any]]:
        """
        Return the config schema of the runnable.

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

        Returns
        -------
        typing.Dict[str, typing.Optional[typing.Any]]
            Successful Response

        Examples
        --------
        from akili import AkiliApi

        client = AkiliApi(
            token="YOUR_TOKEN",
        )
        client.runs.config_schema()
        """
        _response = self._client_wrapper.httpx_client.request(
            "runs/config_schema",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    typing.Dict[str, typing.Optional[typing.Any]],
                    parse_obj_as(
                        type_=typing.Dict[str, typing.Optional[typing.Any]],  # type: ignore
                        object_=_response.json(),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def create_run_feedback(
        self,
        *,
        run_id: str,
        key: str,
        score: typing.Optional[Score] = OMIT,
        value: typing.Optional[Value] = OMIT,
        comment: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.Dict[str, typing.Optional[typing.Any]]:
        """
        Send feedback on an individual run to langsmith

        Note that a successful response means that feedback was successfully
        submitted. It does not guarantee that the feedback is recorded by
        langsmith. Requests may be silently rejected if they are
        unauthenticated or invalid by the server.

        Parameters
        ----------
        run_id : str

        key : str

        score : typing.Optional[Score]

        value : typing.Optional[Value]

        comment : typing.Optional[str]

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

        Returns
        -------
        typing.Dict[str, typing.Optional[typing.Any]]
            Successful Response

        Examples
        --------
        from akili import AkiliApi

        client = AkiliApi(
            token="YOUR_TOKEN",
        )
        client.runs.create_run_feedback(
            run_id="run_id",
            key="key",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            "runs/feedback",
            method="POST",
            json={
                "run_id": run_id,
                "key": key,
                "score": convert_and_respect_annotation_metadata(object_=score, annotation=Score, direction="write"),
                "value": convert_and_respect_annotation_metadata(object_=value, annotation=Value, direction="write"),
                "comment": comment,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    typing.Dict[str, typing.Optional[typing.Any]],
                    parse_obj_as(
                        type_=typing.Dict[str, typing.Optional[typing.Any]],  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    typing.cast(
                        HttpValidationError,
                        parse_obj_as(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)


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

    async def create_run(
        self,
        *,
        thread_id: str,
        input: typing.Optional[Input] = OMIT,
        config: typing.Optional[RunnableConfig] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.Optional[typing.Any]:
        """
        Create a run.

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

        input : typing.Optional[Input]

        config : typing.Optional[RunnableConfig]

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

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

        Examples
        --------
        import asyncio

        from akili import AsyncAkiliApi

        client = AsyncAkiliApi(
            token="YOUR_TOKEN",
        )


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


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            "runs",
            method="POST",
            json={
                "thread_id": thread_id,
                "input": convert_and_respect_annotation_metadata(object_=input, annotation=Input, direction="write"),
                "config": convert_and_respect_annotation_metadata(
                    object_=config, annotation=RunnableConfig, direction="write"
                ),
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    typing.Optional[typing.Any],
                    parse_obj_as(
                        type_=typing.Optional[typing.Any],  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    typing.cast(
                        HttpValidationError,
                        parse_obj_as(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def stream_run(
        self,
        *,
        thread_id: str,
        input: typing.Optional[Input] = OMIT,
        config: typing.Optional[RunnableConfig] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.AsyncIterator[typing.Optional[typing.Any]]:
        """
        Create a run.

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

        input : typing.Optional[Input]

        config : typing.Optional[RunnableConfig]

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

        Yields
        ------
        typing.AsyncIterator[typing.Optional[typing.Any]]
            Successful Response

        Examples
        --------
        import asyncio

        from akili import AsyncAkiliApi

        client = AsyncAkiliApi(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            response = await client.runs.stream_run(
                thread_id="thread_id",
            )
            async for chunk in response:
                yield chunk


        asyncio.run(main())
        """
        async with self._client_wrapper.httpx_client.stream(
            "runs/stream",
            method="POST",
            json={
                "thread_id": thread_id,
                "input": convert_and_respect_annotation_metadata(object_=input, annotation=Input, direction="write"),
                "config": convert_and_respect_annotation_metadata(
                    object_=config, annotation=RunnableConfig, direction="write"
                ),
            },
            request_options=request_options,
            omit=OMIT,
        ) as _response:
            try:
                if 200 <= _response.status_code < 300:
                    _event_source = httpx_sse.EventSource(_response)
                    async for _sse in _event_source.aiter_sse():
                        try:
                            yield typing.cast(
                                typing.Optional[typing.Any],
                                parse_obj_as(
                                    type_=typing.Optional[typing.Any],  # type: ignore
                                    object_=json.loads(_sse.data),
                                ),
                            )
                        except:
                            pass
                    return
                await _response.aread()
                if _response.status_code == 422:
                    raise UnprocessableEntityError(
                        typing.cast(
                            HttpValidationError,
                            parse_obj_as(
                                type_=HttpValidationError,  # type: ignore
                                object_=_response.json(),
                            ),
                        )
                    )
                _response_json = _response.json()
            except JSONDecodeError:
                raise ApiError(status_code=_response.status_code, body=_response.text)
            raise ApiError(status_code=_response.status_code, body=_response_json)

    async def input_schema(
        self, *, request_options: typing.Optional[RequestOptions] = None
    ) -> typing.Dict[str, typing.Optional[typing.Any]]:
        """
        Return the input schema of the runnable.

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

        Returns
        -------
        typing.Dict[str, typing.Optional[typing.Any]]
            Successful Response

        Examples
        --------
        import asyncio

        from akili import AsyncAkiliApi

        client = AsyncAkiliApi(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.runs.input_schema()


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            "runs/input_schema",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    typing.Dict[str, typing.Optional[typing.Any]],
                    parse_obj_as(
                        type_=typing.Dict[str, typing.Optional[typing.Any]],  # type: ignore
                        object_=_response.json(),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def output_schema(
        self, *, request_options: typing.Optional[RequestOptions] = None
    ) -> typing.Dict[str, typing.Optional[typing.Any]]:
        """
        Return the output schema of the runnable.

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

        Returns
        -------
        typing.Dict[str, typing.Optional[typing.Any]]
            Successful Response

        Examples
        --------
        import asyncio

        from akili import AsyncAkiliApi

        client = AsyncAkiliApi(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.runs.output_schema()


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            "runs/output_schema",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    typing.Dict[str, typing.Optional[typing.Any]],
                    parse_obj_as(
                        type_=typing.Dict[str, typing.Optional[typing.Any]],  # type: ignore
                        object_=_response.json(),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def config_schema(
        self, *, request_options: typing.Optional[RequestOptions] = None
    ) -> typing.Dict[str, typing.Optional[typing.Any]]:
        """
        Return the config schema of the runnable.

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

        Returns
        -------
        typing.Dict[str, typing.Optional[typing.Any]]
            Successful Response

        Examples
        --------
        import asyncio

        from akili import AsyncAkiliApi

        client = AsyncAkiliApi(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.runs.config_schema()


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            "runs/config_schema",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    typing.Dict[str, typing.Optional[typing.Any]],
                    parse_obj_as(
                        type_=typing.Dict[str, typing.Optional[typing.Any]],  # type: ignore
                        object_=_response.json(),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def create_run_feedback(
        self,
        *,
        run_id: str,
        key: str,
        score: typing.Optional[Score] = OMIT,
        value: typing.Optional[Value] = OMIT,
        comment: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.Dict[str, typing.Optional[typing.Any]]:
        """
        Send feedback on an individual run to langsmith

        Note that a successful response means that feedback was successfully
        submitted. It does not guarantee that the feedback is recorded by
        langsmith. Requests may be silently rejected if they are
        unauthenticated or invalid by the server.

        Parameters
        ----------
        run_id : str

        key : str

        score : typing.Optional[Score]

        value : typing.Optional[Value]

        comment : typing.Optional[str]

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

        Returns
        -------
        typing.Dict[str, typing.Optional[typing.Any]]
            Successful Response

        Examples
        --------
        import asyncio

        from akili import AsyncAkiliApi

        client = AsyncAkiliApi(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.runs.create_run_feedback(
                run_id="run_id",
                key="key",
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            "runs/feedback",
            method="POST",
            json={
                "run_id": run_id,
                "key": key,
                "score": convert_and_respect_annotation_metadata(object_=score, annotation=Score, direction="write"),
                "value": convert_and_respect_annotation_metadata(object_=value, annotation=Value, direction="write"),
                "comment": comment,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    typing.Dict[str, typing.Optional[typing.Any]],
                    parse_obj_as(
                        type_=typing.Dict[str, typing.Optional[typing.Any]],  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    typing.cast(
                        HttpValidationError,
                        parse_obj_as(
                            type_=HttpValidationError,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)
