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

import typing
from ..core.client_wrapper import SyncClientWrapper
from .types.create_window_input_v1body_wait_until import CreateWindowInputV1BodyWaitUntil
from ..core.request_options import RequestOptions
from ..types.window_id_response import WindowIdResponse
from ..core.jsonable_encoder import jsonable_encoder
from ..core.pydantic_utilities import parse_obj_as
from json.decoder import JSONDecodeError
from ..core.api_error import ApiError
from ..types.window_response import WindowResponse
from .types.window_load_url_v1body_wait_until import WindowLoadUrlV1BodyWaitUntil
from ..types.empty_response import EmptyResponse
from ..types.prompt_content_config import PromptContentConfig
from ..types.ai_prompt_response import AiPromptResponse
from ..core.serialization import convert_and_respect_annotation_metadata
from ..types.scrape_response import ScrapeResponse
from ..types.summary_config import SummaryConfig
from ..core.client_wrapper import AsyncClientWrapper

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


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

    def create(
        self,
        session_id: str,
        *,
        screen_resolution: typing.Optional[str] = OMIT,
        url: typing.Optional[str] = OMIT,
        wait_until: typing.Optional[CreateWindowInputV1BodyWaitUntil] = OMIT,
        wait_until_timeout_seconds: typing.Optional[int] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> WindowIdResponse:
        """
        Parameters
        ----------
        session_id : str
            ID of the session that owns the window.

        screen_resolution : typing.Optional[str]
            Affects the live view configuration. By default, a live view will fill the parent frame (or local window if loaded directly) when initially loaded, causing the browser window to be resized to match. This parameter can be used to instead configure the returned liveViewUrl so that the live view is loaded with fixed dimensions (e.g. 1280x720), resizing the browser window to match, and then disallows any further resizing from the live view.

        url : typing.Optional[str]
            Initial url to navigate to

        wait_until : typing.Optional[CreateWindowInputV1BodyWaitUntil]
            Wait until the specified loading event occurs. Defaults to 'load', which waits until the page dom and it's assets have loaded. 'domContentLoaded' will wait until the dom has loaded, and 'complete' will wait until the page and all it's iframes have loaded it's dom and assets.

        wait_until_timeout_seconds : typing.Optional[int]
            Maximum time in seconds to wait for the specified loading event to occur before timing out.

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

        Returns
        -------
        WindowIdResponse
            Created

        Examples
        --------
        from airtop import Airtop

        client = Airtop(
            api_key="YOUR_API_KEY",
        )
        client.windows.create(
            session_id="6aac6f73-bd89-4a76-ab32-5a6c422e8b0b",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"sessions/{jsonable_encoder(session_id)}/windows",
            method="POST",
            json={
                "screenResolution": screen_resolution,
                "url": url,
                "waitUntil": wait_until,
                "waitUntilTimeoutSeconds": wait_until_timeout_seconds,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    WindowIdResponse,
                    parse_obj_as(
                        type_=WindowIdResponse,  # 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 get_window_info(
        self,
        session_id: str,
        window_id: str,
        *,
        include_navigation_bar: typing.Optional[bool] = None,
        disable_resize: typing.Optional[bool] = None,
        screen_resolution: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> WindowResponse:
        """
        Parameters
        ----------
        session_id : str
            ID of the session that owns the window.

        window_id : str
            ID of the browser window, which can either be a normal AirTop windowId or a [CDP TargetId](https://chromedevtools.github.io/devtools-protocol/tot/Target/#type-TargetID) from a browser automation library like Puppeteer (typically associated with the page or main frame). Our SDKs will handle retrieving a TargetId for you from various popular browser automation libraries, but we also have details in our guides on how to do it manually.

        include_navigation_bar : typing.Optional[bool]
            Affects the live view configuration. A navigation bar is not shown in the live view of a browser by default. Set this to true to configure the returned liveViewUrl so that a navigation bar is rendered, allowing users to easily navigate the browser to other pages from the live view.

        disable_resize : typing.Optional[bool]
            Affects the live view configuration. Set to true to configure the returned liveViewUrl so that the ability to resize the browser window from the live view is disabled (resizing is allowed by default). Note that, at initial load, the live view will automatically fill the parent frame (or local window if loaded directly) and cause the browser window to be resized to match. This parameter does not affect that initial load behavior. See screenResolution for a way to set a fixed size for the live view.

        screen_resolution : typing.Optional[str]
            Affects the live view configuration. By default, a live view will fill the parent frame (or local window if loaded directly) when initially loaded, causing the browser window to be resized to match. This parameter can be used to instead configure the returned liveViewUrl so that the live view is loaded with fixed dimensions (e.g. 1280x720), resizing the browser window to match, and then disallows any further resizing from the live view.

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

        Returns
        -------
        WindowResponse
            Created

        Examples
        --------
        from airtop import Airtop

        client = Airtop(
            api_key="YOUR_API_KEY",
        )
        client.windows.get_window_info(
            session_id="6aac6f73-bd89-4a76-ab32-5a6c422e8b0b",
            window_id="7334da2a-91b0-42c5-6156-76a5eba87430",
            screen_resolution="1280x720",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"sessions/{jsonable_encoder(session_id)}/windows/{jsonable_encoder(window_id)}",
            method="GET",
            params={
                "includeNavigationBar": include_navigation_bar,
                "disableResize": disable_resize,
                "screenResolution": screen_resolution,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    WindowResponse,
                    parse_obj_as(
                        type_=WindowResponse,  # 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 load_url(
        self,
        session_id: str,
        window_id: str,
        *,
        url: str,
        wait_until: typing.Optional[WindowLoadUrlV1BodyWaitUntil] = OMIT,
        wait_until_timeout_seconds: typing.Optional[int] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> EmptyResponse:
        """
        Parameters
        ----------
        session_id : str
            ID of the session that owns the window.

        window_id : str
            Airtop window ID of the browser window.

        url : str
            Url to navigate to

        wait_until : typing.Optional[WindowLoadUrlV1BodyWaitUntil]
            Wait until the specified loading event occurs. Defaults to 'load', which waits until the page dom and it's assets have loaded. 'domContentLoaded' will wait until the dom has loaded, and 'complete' will wait until the page and all it's iframes have loaded it's dom and assets.

        wait_until_timeout_seconds : typing.Optional[int]
            Maximum time in seconds to wait for the specified loading event to occur before timing out.

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

        Returns
        -------
        EmptyResponse
            Created

        Examples
        --------
        from airtop import Airtop

        client = Airtop(
            api_key="YOUR_API_KEY",
        )
        client.windows.load_url(
            session_id="6aac6f73-bd89-4a76-ab32-5a6c422e8b0b",
            window_id="7334da2a-91b0-42c5-6156-76a5eba87430",
            url="https://www.airtop.ai",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"sessions/{jsonable_encoder(session_id)}/windows/{jsonable_encoder(window_id)}",
            method="POST",
            json={
                "url": url,
                "waitUntil": wait_until,
                "waitUntilTimeoutSeconds": wait_until_timeout_seconds,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    EmptyResponse,
                    parse_obj_as(
                        type_=EmptyResponse,  # 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 close(
        self, session_id: str, window_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> WindowIdResponse:
        """
        Parameters
        ----------
        session_id : str
            ID of the session that owns the window.

        window_id : str
            Airtop window ID of the browser window.

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

        Returns
        -------
        WindowIdResponse
            OK

        Examples
        --------
        from airtop import Airtop

        client = Airtop(
            api_key="YOUR_API_KEY",
        )
        client.windows.close(
            session_id="6aac6f73-bd89-4a76-ab32-5a6c422e8b0b",
            window_id="7334da2a-91b0-42c5-6156-76a5eba87430",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"sessions/{jsonable_encoder(session_id)}/windows/{jsonable_encoder(window_id)}",
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    WindowIdResponse,
                    parse_obj_as(
                        type_=WindowIdResponse,  # 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 prompt_content(
        self,
        session_id: str,
        window_id: str,
        *,
        prompt: str,
        client_request_id: typing.Optional[str] = OMIT,
        configuration: typing.Optional[PromptContentConfig] = OMIT,
        cost_threshold_credits: typing.Optional[int] = OMIT,
        follow_pagination_links: typing.Optional[bool] = OMIT,
        time_threshold_seconds: typing.Optional[int] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AiPromptResponse:
        """
        Parameters
        ----------
        session_id : str
            The session id for the window.

        window_id : str
            The Airtop window id of the browser window to target with an Airtop AI prompt.

        prompt : str
            The prompt to submit about the content in the browser window.

        client_request_id : typing.Optional[str]

        configuration : typing.Optional[PromptContentConfig]
            Request configuration

        cost_threshold_credits : typing.Optional[int]
            A credit threshold that, once exceeded, will cause the operation to be cancelled. Note that this is *not* a hard limit, but a threshold that is checked periodically during the course of fulfilling the request. A default threshold is used if not specified, but you can use this option to increase or decrease as needed. Set to 0 to disable this feature entirely (not recommended).

        follow_pagination_links : typing.Optional[bool]
            Make a best effort attempt to load more content items than are originally displayed on the page, e.g. by following pagination links, clicking controls to load more content, utilizing infinite scrolling, etc. This can be quite a bit more costly, but may be necessary for sites that require additional interaction to show the needed results. You can provide constraints in your prompt (e.g. on the total number of pages or results to consider).

        time_threshold_seconds : typing.Optional[int]
            A time threshold in seconds that, once exceeded, will cause the operation to be cancelled. Note that this is *not* a hard limit, but a threshold that is checked periodically during the course of fulfilling the request. A default threshold is used if not specified, but you can use this option to increase or decrease as needed. Set to 0 to disable this feature entirely (not recommended).

            This setting does not extend the maximum session duration provided at the time of session creation.

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

        Returns
        -------
        AiPromptResponse
            Created

        Examples
        --------
        from airtop import Airtop

        client = Airtop(
            api_key="YOUR_API_KEY",
        )
        client.windows.prompt_content(
            session_id="6aac6f73-bd89-4a76-ab32-5a6c422e8b0b",
            window_id="0334da2a-91b0-42c5-6156-76a5eba87430",
            prompt="What is the main idea of this page?",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"sessions/{jsonable_encoder(session_id)}/windows/{jsonable_encoder(window_id)}/prompt-content",
            method="POST",
            json={
                "clientRequestId": client_request_id,
                "configuration": convert_and_respect_annotation_metadata(
                    object_=configuration, annotation=PromptContentConfig, direction="write"
                ),
                "costThresholdCredits": cost_threshold_credits,
                "followPaginationLinks": follow_pagination_links,
                "prompt": prompt,
                "timeThresholdSeconds": time_threshold_seconds,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    AiPromptResponse,
                    parse_obj_as(
                        type_=AiPromptResponse,  # 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 scrape_content(
        self,
        session_id: str,
        window_id: str,
        *,
        client_request_id: typing.Optional[str] = OMIT,
        cost_threshold_credits: typing.Optional[int] = OMIT,
        time_threshold_seconds: typing.Optional[int] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ScrapeResponse:
        """
        Parameters
        ----------
        session_id : str
            The session id for the window.

        window_id : str
            The Airtop window id of the browser window to scrape.

        client_request_id : typing.Optional[str]

        cost_threshold_credits : typing.Optional[int]
            A credit threshold that, once exceeded, will cause the operation to be cancelled. Note that this is *not* a hard limit, but a threshold that is checked periodically during the course of fulfilling the request. A default threshold is used if not specified, but you can use this option to increase or decrease as needed. Set to 0 to disable this feature entirely (not recommended).

        time_threshold_seconds : typing.Optional[int]
            A time threshold in seconds that, once exceeded, will cause the operation to be cancelled. Note that this is *not* a hard limit, but a threshold that is checked periodically during the course of fulfilling the request. A default threshold is used if not specified, but you can use this option to increase or decrease as needed. Set to 0 to disable this feature entirely (not recommended).

            This setting does not extend the maximum session duration provided at the time of session creation.

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

        Returns
        -------
        ScrapeResponse
            Created

        Examples
        --------
        from airtop import Airtop

        client = Airtop(
            api_key="YOUR_API_KEY",
        )
        client.windows.scrape_content(
            session_id="6aac6f73-bd89-4a76-ab32-5a6c422e8b0b",
            window_id="0334da2a-91b0-42c5-6156-76a5eba87430",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"sessions/{jsonable_encoder(session_id)}/windows/{jsonable_encoder(window_id)}/scrape-content",
            method="POST",
            json={
                "clientRequestId": client_request_id,
                "costThresholdCredits": cost_threshold_credits,
                "timeThresholdSeconds": time_threshold_seconds,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    ScrapeResponse,
                    parse_obj_as(
                        type_=ScrapeResponse,  # 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 summarize_content(
        self,
        session_id: str,
        window_id: str,
        *,
        client_request_id: typing.Optional[str] = OMIT,
        configuration: typing.Optional[SummaryConfig] = OMIT,
        cost_threshold_credits: typing.Optional[int] = OMIT,
        prompt: typing.Optional[str] = OMIT,
        time_threshold_seconds: typing.Optional[int] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AiPromptResponse:
        """
        Parameters
        ----------
        session_id : str
            The session id for the window.

        window_id : str
            The Airtop window id of the browser window to summarize.

        client_request_id : typing.Optional[str]

        configuration : typing.Optional[SummaryConfig]
            Request configuration

        cost_threshold_credits : typing.Optional[int]
            A credit threshold that, once exceeded, will cause the operation to be cancelled. Note that this is *not* a hard limit, but a threshold that is checked periodically during the course of fulfilling the request. A default threshold is used if not specified, but you can use this option to increase or decrease as needed. Set to 0 to disable this feature entirely (not recommended).

        prompt : typing.Optional[str]
            An optional prompt providing the Airtop AI model with additional direction or constraints about the summary (such as desired length).

        time_threshold_seconds : typing.Optional[int]
            A time threshold in seconds that, once exceeded, will cause the operation to be cancelled. Note that this is *not* a hard limit, but a threshold that is checked periodically during the course of fulfilling the request. A default threshold is used if not specified, but you can use this option to increase or decrease as needed. Set to 0 to disable this feature entirely (not recommended).

            This setting does not extend the maximum session duration provided at the time of session creation.

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

        Returns
        -------
        AiPromptResponse
            Created

        Examples
        --------
        from airtop import Airtop

        client = Airtop(
            api_key="YOUR_API_KEY",
        )
        client.windows.summarize_content(
            session_id="6aac6f73-bd89-4a76-ab32-5a6c422e8b0b",
            window_id="0334da2a-91b0-42c5-6156-76a5eba87430",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"sessions/{jsonable_encoder(session_id)}/windows/{jsonable_encoder(window_id)}/summarize-content",
            method="POST",
            json={
                "clientRequestId": client_request_id,
                "configuration": convert_and_respect_annotation_metadata(
                    object_=configuration, annotation=SummaryConfig, direction="write"
                ),
                "costThresholdCredits": cost_threshold_credits,
                "prompt": prompt,
                "timeThresholdSeconds": time_threshold_seconds,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    AiPromptResponse,
                    parse_obj_as(
                        type_=AiPromptResponse,  # 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 AsyncWindowsClient:
    def __init__(self, *, client_wrapper: AsyncClientWrapper):
        self._client_wrapper = client_wrapper

    async def create(
        self,
        session_id: str,
        *,
        screen_resolution: typing.Optional[str] = OMIT,
        url: typing.Optional[str] = OMIT,
        wait_until: typing.Optional[CreateWindowInputV1BodyWaitUntil] = OMIT,
        wait_until_timeout_seconds: typing.Optional[int] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> WindowIdResponse:
        """
        Parameters
        ----------
        session_id : str
            ID of the session that owns the window.

        screen_resolution : typing.Optional[str]
            Affects the live view configuration. By default, a live view will fill the parent frame (or local window if loaded directly) when initially loaded, causing the browser window to be resized to match. This parameter can be used to instead configure the returned liveViewUrl so that the live view is loaded with fixed dimensions (e.g. 1280x720), resizing the browser window to match, and then disallows any further resizing from the live view.

        url : typing.Optional[str]
            Initial url to navigate to

        wait_until : typing.Optional[CreateWindowInputV1BodyWaitUntil]
            Wait until the specified loading event occurs. Defaults to 'load', which waits until the page dom and it's assets have loaded. 'domContentLoaded' will wait until the dom has loaded, and 'complete' will wait until the page and all it's iframes have loaded it's dom and assets.

        wait_until_timeout_seconds : typing.Optional[int]
            Maximum time in seconds to wait for the specified loading event to occur before timing out.

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

        Returns
        -------
        WindowIdResponse
            Created

        Examples
        --------
        import asyncio

        from airtop import AsyncAirtop

        client = AsyncAirtop(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.windows.create(
                session_id="6aac6f73-bd89-4a76-ab32-5a6c422e8b0b",
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"sessions/{jsonable_encoder(session_id)}/windows",
            method="POST",
            json={
                "screenResolution": screen_resolution,
                "url": url,
                "waitUntil": wait_until,
                "waitUntilTimeoutSeconds": wait_until_timeout_seconds,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    WindowIdResponse,
                    parse_obj_as(
                        type_=WindowIdResponse,  # 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 get_window_info(
        self,
        session_id: str,
        window_id: str,
        *,
        include_navigation_bar: typing.Optional[bool] = None,
        disable_resize: typing.Optional[bool] = None,
        screen_resolution: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> WindowResponse:
        """
        Parameters
        ----------
        session_id : str
            ID of the session that owns the window.

        window_id : str
            ID of the browser window, which can either be a normal AirTop windowId or a [CDP TargetId](https://chromedevtools.github.io/devtools-protocol/tot/Target/#type-TargetID) from a browser automation library like Puppeteer (typically associated with the page or main frame). Our SDKs will handle retrieving a TargetId for you from various popular browser automation libraries, but we also have details in our guides on how to do it manually.

        include_navigation_bar : typing.Optional[bool]
            Affects the live view configuration. A navigation bar is not shown in the live view of a browser by default. Set this to true to configure the returned liveViewUrl so that a navigation bar is rendered, allowing users to easily navigate the browser to other pages from the live view.

        disable_resize : typing.Optional[bool]
            Affects the live view configuration. Set to true to configure the returned liveViewUrl so that the ability to resize the browser window from the live view is disabled (resizing is allowed by default). Note that, at initial load, the live view will automatically fill the parent frame (or local window if loaded directly) and cause the browser window to be resized to match. This parameter does not affect that initial load behavior. See screenResolution for a way to set a fixed size for the live view.

        screen_resolution : typing.Optional[str]
            Affects the live view configuration. By default, a live view will fill the parent frame (or local window if loaded directly) when initially loaded, causing the browser window to be resized to match. This parameter can be used to instead configure the returned liveViewUrl so that the live view is loaded with fixed dimensions (e.g. 1280x720), resizing the browser window to match, and then disallows any further resizing from the live view.

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

        Returns
        -------
        WindowResponse
            Created

        Examples
        --------
        import asyncio

        from airtop import AsyncAirtop

        client = AsyncAirtop(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.windows.get_window_info(
                session_id="6aac6f73-bd89-4a76-ab32-5a6c422e8b0b",
                window_id="7334da2a-91b0-42c5-6156-76a5eba87430",
                screen_resolution="1280x720",
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"sessions/{jsonable_encoder(session_id)}/windows/{jsonable_encoder(window_id)}",
            method="GET",
            params={
                "includeNavigationBar": include_navigation_bar,
                "disableResize": disable_resize,
                "screenResolution": screen_resolution,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    WindowResponse,
                    parse_obj_as(
                        type_=WindowResponse,  # 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 load_url(
        self,
        session_id: str,
        window_id: str,
        *,
        url: str,
        wait_until: typing.Optional[WindowLoadUrlV1BodyWaitUntil] = OMIT,
        wait_until_timeout_seconds: typing.Optional[int] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> EmptyResponse:
        """
        Parameters
        ----------
        session_id : str
            ID of the session that owns the window.

        window_id : str
            Airtop window ID of the browser window.

        url : str
            Url to navigate to

        wait_until : typing.Optional[WindowLoadUrlV1BodyWaitUntil]
            Wait until the specified loading event occurs. Defaults to 'load', which waits until the page dom and it's assets have loaded. 'domContentLoaded' will wait until the dom has loaded, and 'complete' will wait until the page and all it's iframes have loaded it's dom and assets.

        wait_until_timeout_seconds : typing.Optional[int]
            Maximum time in seconds to wait for the specified loading event to occur before timing out.

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

        Returns
        -------
        EmptyResponse
            Created

        Examples
        --------
        import asyncio

        from airtop import AsyncAirtop

        client = AsyncAirtop(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.windows.load_url(
                session_id="6aac6f73-bd89-4a76-ab32-5a6c422e8b0b",
                window_id="7334da2a-91b0-42c5-6156-76a5eba87430",
                url="https://www.airtop.ai",
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"sessions/{jsonable_encoder(session_id)}/windows/{jsonable_encoder(window_id)}",
            method="POST",
            json={
                "url": url,
                "waitUntil": wait_until,
                "waitUntilTimeoutSeconds": wait_until_timeout_seconds,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    EmptyResponse,
                    parse_obj_as(
                        type_=EmptyResponse,  # 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 close(
        self, session_id: str, window_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> WindowIdResponse:
        """
        Parameters
        ----------
        session_id : str
            ID of the session that owns the window.

        window_id : str
            Airtop window ID of the browser window.

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

        Returns
        -------
        WindowIdResponse
            OK

        Examples
        --------
        import asyncio

        from airtop import AsyncAirtop

        client = AsyncAirtop(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.windows.close(
                session_id="6aac6f73-bd89-4a76-ab32-5a6c422e8b0b",
                window_id="7334da2a-91b0-42c5-6156-76a5eba87430",
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"sessions/{jsonable_encoder(session_id)}/windows/{jsonable_encoder(window_id)}",
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    WindowIdResponse,
                    parse_obj_as(
                        type_=WindowIdResponse,  # 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 prompt_content(
        self,
        session_id: str,
        window_id: str,
        *,
        prompt: str,
        client_request_id: typing.Optional[str] = OMIT,
        configuration: typing.Optional[PromptContentConfig] = OMIT,
        cost_threshold_credits: typing.Optional[int] = OMIT,
        follow_pagination_links: typing.Optional[bool] = OMIT,
        time_threshold_seconds: typing.Optional[int] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AiPromptResponse:
        """
        Parameters
        ----------
        session_id : str
            The session id for the window.

        window_id : str
            The Airtop window id of the browser window to target with an Airtop AI prompt.

        prompt : str
            The prompt to submit about the content in the browser window.

        client_request_id : typing.Optional[str]

        configuration : typing.Optional[PromptContentConfig]
            Request configuration

        cost_threshold_credits : typing.Optional[int]
            A credit threshold that, once exceeded, will cause the operation to be cancelled. Note that this is *not* a hard limit, but a threshold that is checked periodically during the course of fulfilling the request. A default threshold is used if not specified, but you can use this option to increase or decrease as needed. Set to 0 to disable this feature entirely (not recommended).

        follow_pagination_links : typing.Optional[bool]
            Make a best effort attempt to load more content items than are originally displayed on the page, e.g. by following pagination links, clicking controls to load more content, utilizing infinite scrolling, etc. This can be quite a bit more costly, but may be necessary for sites that require additional interaction to show the needed results. You can provide constraints in your prompt (e.g. on the total number of pages or results to consider).

        time_threshold_seconds : typing.Optional[int]
            A time threshold in seconds that, once exceeded, will cause the operation to be cancelled. Note that this is *not* a hard limit, but a threshold that is checked periodically during the course of fulfilling the request. A default threshold is used if not specified, but you can use this option to increase or decrease as needed. Set to 0 to disable this feature entirely (not recommended).

            This setting does not extend the maximum session duration provided at the time of session creation.

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

        Returns
        -------
        AiPromptResponse
            Created

        Examples
        --------
        import asyncio

        from airtop import AsyncAirtop

        client = AsyncAirtop(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.windows.prompt_content(
                session_id="6aac6f73-bd89-4a76-ab32-5a6c422e8b0b",
                window_id="0334da2a-91b0-42c5-6156-76a5eba87430",
                prompt="What is the main idea of this page?",
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"sessions/{jsonable_encoder(session_id)}/windows/{jsonable_encoder(window_id)}/prompt-content",
            method="POST",
            json={
                "clientRequestId": client_request_id,
                "configuration": convert_and_respect_annotation_metadata(
                    object_=configuration, annotation=PromptContentConfig, direction="write"
                ),
                "costThresholdCredits": cost_threshold_credits,
                "followPaginationLinks": follow_pagination_links,
                "prompt": prompt,
                "timeThresholdSeconds": time_threshold_seconds,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    AiPromptResponse,
                    parse_obj_as(
                        type_=AiPromptResponse,  # 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 scrape_content(
        self,
        session_id: str,
        window_id: str,
        *,
        client_request_id: typing.Optional[str] = OMIT,
        cost_threshold_credits: typing.Optional[int] = OMIT,
        time_threshold_seconds: typing.Optional[int] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ScrapeResponse:
        """
        Parameters
        ----------
        session_id : str
            The session id for the window.

        window_id : str
            The Airtop window id of the browser window to scrape.

        client_request_id : typing.Optional[str]

        cost_threshold_credits : typing.Optional[int]
            A credit threshold that, once exceeded, will cause the operation to be cancelled. Note that this is *not* a hard limit, but a threshold that is checked periodically during the course of fulfilling the request. A default threshold is used if not specified, but you can use this option to increase or decrease as needed. Set to 0 to disable this feature entirely (not recommended).

        time_threshold_seconds : typing.Optional[int]
            A time threshold in seconds that, once exceeded, will cause the operation to be cancelled. Note that this is *not* a hard limit, but a threshold that is checked periodically during the course of fulfilling the request. A default threshold is used if not specified, but you can use this option to increase or decrease as needed. Set to 0 to disable this feature entirely (not recommended).

            This setting does not extend the maximum session duration provided at the time of session creation.

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

        Returns
        -------
        ScrapeResponse
            Created

        Examples
        --------
        import asyncio

        from airtop import AsyncAirtop

        client = AsyncAirtop(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.windows.scrape_content(
                session_id="6aac6f73-bd89-4a76-ab32-5a6c422e8b0b",
                window_id="0334da2a-91b0-42c5-6156-76a5eba87430",
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"sessions/{jsonable_encoder(session_id)}/windows/{jsonable_encoder(window_id)}/scrape-content",
            method="POST",
            json={
                "clientRequestId": client_request_id,
                "costThresholdCredits": cost_threshold_credits,
                "timeThresholdSeconds": time_threshold_seconds,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    ScrapeResponse,
                    parse_obj_as(
                        type_=ScrapeResponse,  # 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 summarize_content(
        self,
        session_id: str,
        window_id: str,
        *,
        client_request_id: typing.Optional[str] = OMIT,
        configuration: typing.Optional[SummaryConfig] = OMIT,
        cost_threshold_credits: typing.Optional[int] = OMIT,
        prompt: typing.Optional[str] = OMIT,
        time_threshold_seconds: typing.Optional[int] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AiPromptResponse:
        """
        Parameters
        ----------
        session_id : str
            The session id for the window.

        window_id : str
            The Airtop window id of the browser window to summarize.

        client_request_id : typing.Optional[str]

        configuration : typing.Optional[SummaryConfig]
            Request configuration

        cost_threshold_credits : typing.Optional[int]
            A credit threshold that, once exceeded, will cause the operation to be cancelled. Note that this is *not* a hard limit, but a threshold that is checked periodically during the course of fulfilling the request. A default threshold is used if not specified, but you can use this option to increase or decrease as needed. Set to 0 to disable this feature entirely (not recommended).

        prompt : typing.Optional[str]
            An optional prompt providing the Airtop AI model with additional direction or constraints about the summary (such as desired length).

        time_threshold_seconds : typing.Optional[int]
            A time threshold in seconds that, once exceeded, will cause the operation to be cancelled. Note that this is *not* a hard limit, but a threshold that is checked periodically during the course of fulfilling the request. A default threshold is used if not specified, but you can use this option to increase or decrease as needed. Set to 0 to disable this feature entirely (not recommended).

            This setting does not extend the maximum session duration provided at the time of session creation.

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

        Returns
        -------
        AiPromptResponse
            Created

        Examples
        --------
        import asyncio

        from airtop import AsyncAirtop

        client = AsyncAirtop(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.windows.summarize_content(
                session_id="6aac6f73-bd89-4a76-ab32-5a6c422e8b0b",
                window_id="0334da2a-91b0-42c5-6156-76a5eba87430",
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"sessions/{jsonable_encoder(session_id)}/windows/{jsonable_encoder(window_id)}/summarize-content",
            method="POST",
            json={
                "clientRequestId": client_request_id,
                "configuration": convert_and_respect_annotation_metadata(
                    object_=configuration, annotation=SummaryConfig, direction="write"
                ),
                "costThresholdCredits": cost_threshold_credits,
                "prompt": prompt,
                "timeThresholdSeconds": time_threshold_seconds,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    AiPromptResponse,
                    parse_obj_as(
                        type_=AiPromptResponse,  # 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)
