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

from .basesdk import BaseSDK
from jsonpath import JSONPath
from openrouter import components, errors, operations, utils
from openrouter._hooks import HookContext
from openrouter.types import Nullable, OptionalNullable, UNSET
from openrouter.utils import get_security_from_env
from openrouter.utils.unmarshal_json_response import unmarshal_json_response
from typing import Any, Awaitable, Dict, List, Mapping, Optional, Union


class Presets(BaseSDK):
    r"""Presets endpoints"""

    def list(
        self,
        *,
        http_referer: Optional[str] = None,
        x_open_router_title: Optional[str] = None,
        x_open_router_categories: Optional[str] = None,
        offset: Optional[int] = None,
        limit: Optional[int] = None,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> Optional[operations.ListPresetsResponse]:
        r"""List presets

        Lists all presets for the authenticated user, ordered by most recently updated first.

        :param http_referer: The app identifier should be your app's URL and is used as the primary identifier for rankings.
            This is used to track API usage per application.

        :param x_open_router_title: The app display name allows you to customize how your app appears in OpenRouter's dashboard.

        :param x_open_router_categories: Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.

        :param offset: Number of records to skip for pagination
        :param limit: Maximum number of records to return (max 100)
        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = operations.ListPresetsRequest(
            http_referer=http_referer,
            x_open_router_title=x_open_router_title,
            x_open_router_categories=x_open_router_categories,
            offset=offset,
            limit=limit,
        )

        req = self._build_request(
            method="GET",
            path="/presets",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=False,
            request_has_path_params=False,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/json",
            http_headers=http_headers,
            _globals=operations.ListPresetsGlobals(
                http_referer=self.sdk_configuration.globals.http_referer,
                x_open_router_title=self.sdk_configuration.globals.x_open_router_title,
                x_open_router_categories=self.sdk_configuration.globals.x_open_router_categories,
            ),
            security=self.sdk_configuration.security,
            allow_empty_value=None,
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config
            else:
                retries = utils.RetryConfig(
                    "backoff", utils.BackoffStrategy(500, 60000, 1.5, 3600000), True
                )

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["5XX"])

        http_res = self.do_request(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="listPresets",
                oauth2_scopes=None,
                security_source=get_security_from_env(
                    self.sdk_configuration.security, components.Security
                ),
            ),
            request=req,
            error_status_codes=["400", "401", "4XX", "500", "5XX"],
            retry_config=retry_config,
        )

        def next_func() -> Optional[operations.ListPresetsResponse]:
            body = utils.unmarshal_json(http_res.text, Union[Dict[Any, Any], List[Any]])

            offset = request.offset if not request.offset is None else 0

            if not http_res.text:
                return None
            results = JSONPath("$.data").parse(body)
            if len(results) == 0 or len(results[0]) == 0:
                return None
            limit = request.limit if not request.limit is None else 0
            if len(results[0]) < limit:
                return None
            next_offset = offset + len(results[0])

            return self.list(
                http_referer=http_referer,
                x_open_router_title=x_open_router_title,
                x_open_router_categories=x_open_router_categories,
                offset=next_offset,
                limit=limit,
                retries=retries,
            )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/json"):
            return operations.ListPresetsResponse(
                result=unmarshal_json_response(
                    components.ListPresetsResponse, http_res
                ),
                next=next_func,
            )
        if utils.match_response(http_res, "400", "application/json"):
            response_data = unmarshal_json_response(
                errors.BadRequestResponseErrorData, http_res
            )
            raise errors.BadRequestResponseError(response_data, http_res)
        if utils.match_response(http_res, "401", "application/json"):
            response_data = unmarshal_json_response(
                errors.UnauthorizedResponseErrorData, http_res
            )
            raise errors.UnauthorizedResponseError(response_data, http_res)
        if utils.match_response(http_res, "500", "application/json"):
            response_data = unmarshal_json_response(
                errors.InternalServerResponseErrorData, http_res
            )
            raise errors.InternalServerResponseError(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.OpenRouterDefaultError(
                "API error occurred", http_res, http_res_text
            )
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.OpenRouterDefaultError(
                "API error occurred", http_res, http_res_text
            )

        raise errors.OpenRouterDefaultError("Unexpected response received", http_res)

    async def list_async(
        self,
        *,
        http_referer: Optional[str] = None,
        x_open_router_title: Optional[str] = None,
        x_open_router_categories: Optional[str] = None,
        offset: Optional[int] = None,
        limit: Optional[int] = None,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> Optional[operations.ListPresetsResponse]:
        r"""List presets

        Lists all presets for the authenticated user, ordered by most recently updated first.

        :param http_referer: The app identifier should be your app's URL and is used as the primary identifier for rankings.
            This is used to track API usage per application.

        :param x_open_router_title: The app display name allows you to customize how your app appears in OpenRouter's dashboard.

        :param x_open_router_categories: Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.

        :param offset: Number of records to skip for pagination
        :param limit: Maximum number of records to return (max 100)
        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = operations.ListPresetsRequest(
            http_referer=http_referer,
            x_open_router_title=x_open_router_title,
            x_open_router_categories=x_open_router_categories,
            offset=offset,
            limit=limit,
        )

        req = self._build_request_async(
            method="GET",
            path="/presets",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=False,
            request_has_path_params=False,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/json",
            http_headers=http_headers,
            _globals=operations.ListPresetsGlobals(
                http_referer=self.sdk_configuration.globals.http_referer,
                x_open_router_title=self.sdk_configuration.globals.x_open_router_title,
                x_open_router_categories=self.sdk_configuration.globals.x_open_router_categories,
            ),
            security=self.sdk_configuration.security,
            allow_empty_value=None,
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config
            else:
                retries = utils.RetryConfig(
                    "backoff", utils.BackoffStrategy(500, 60000, 1.5, 3600000), True
                )

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["5XX"])

        http_res = await self.do_request_async(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="listPresets",
                oauth2_scopes=None,
                security_source=get_security_from_env(
                    self.sdk_configuration.security, components.Security
                ),
            ),
            request=req,
            error_status_codes=["400", "401", "4XX", "500", "5XX"],
            retry_config=retry_config,
        )

        def next_func() -> Awaitable[Optional[operations.ListPresetsResponse]]:
            body = utils.unmarshal_json(http_res.text, Union[Dict[Any, Any], List[Any]])

            async def empty_result():
                return None

            offset = request.offset if not request.offset is None else 0

            if not http_res.text:
                return empty_result()
            results = JSONPath("$.data").parse(body)
            if len(results) == 0 or len(results[0]) == 0:
                return empty_result()
            limit = request.limit if not request.limit is None else 0
            if len(results[0]) < limit:
                return empty_result()
            next_offset = offset + len(results[0])

            return self.list_async(
                http_referer=http_referer,
                x_open_router_title=x_open_router_title,
                x_open_router_categories=x_open_router_categories,
                offset=next_offset,
                limit=limit,
                retries=retries,
            )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/json"):
            return operations.ListPresetsResponse(
                result=unmarshal_json_response(
                    components.ListPresetsResponse, http_res
                ),
                next=next_func,
            )
        if utils.match_response(http_res, "400", "application/json"):
            response_data = unmarshal_json_response(
                errors.BadRequestResponseErrorData, http_res
            )
            raise errors.BadRequestResponseError(response_data, http_res)
        if utils.match_response(http_res, "401", "application/json"):
            response_data = unmarshal_json_response(
                errors.UnauthorizedResponseErrorData, http_res
            )
            raise errors.UnauthorizedResponseError(response_data, http_res)
        if utils.match_response(http_res, "500", "application/json"):
            response_data = unmarshal_json_response(
                errors.InternalServerResponseErrorData, http_res
            )
            raise errors.InternalServerResponseError(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.OpenRouterDefaultError(
                "API error occurred", http_res, http_res_text
            )
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.OpenRouterDefaultError(
                "API error occurred", http_res, http_res_text
            )

        raise errors.OpenRouterDefaultError("Unexpected response received", http_res)

    def get(
        self,
        *,
        slug: str,
        http_referer: Optional[str] = None,
        x_open_router_title: Optional[str] = None,
        x_open_router_categories: Optional[str] = None,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> components.GetPresetResponse:
        r"""Get a preset

        Retrieves a preset by its slug with its currently designated version inline.

        :param slug: URL-safe slug identifying the preset.
        :param http_referer: The app identifier should be your app's URL and is used as the primary identifier for rankings.
            This is used to track API usage per application.

        :param x_open_router_title: The app display name allows you to customize how your app appears in OpenRouter's dashboard.

        :param x_open_router_categories: Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.

        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = operations.GetPresetRequest(
            http_referer=http_referer,
            x_open_router_title=x_open_router_title,
            x_open_router_categories=x_open_router_categories,
            slug=slug,
        )

        req = self._build_request(
            method="GET",
            path="/presets/{slug}",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=False,
            request_has_path_params=True,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/json",
            http_headers=http_headers,
            _globals=operations.GetPresetGlobals(
                http_referer=self.sdk_configuration.globals.http_referer,
                x_open_router_title=self.sdk_configuration.globals.x_open_router_title,
                x_open_router_categories=self.sdk_configuration.globals.x_open_router_categories,
            ),
            security=self.sdk_configuration.security,
            allow_empty_value=None,
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config
            else:
                retries = utils.RetryConfig(
                    "backoff", utils.BackoffStrategy(500, 60000, 1.5, 3600000), True
                )

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["5XX"])

        http_res = self.do_request(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="getPreset",
                oauth2_scopes=None,
                security_source=get_security_from_env(
                    self.sdk_configuration.security, components.Security
                ),
            ),
            request=req,
            error_status_codes=["400", "401", "404", "4XX", "500", "5XX"],
            retry_config=retry_config,
        )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/json"):
            return unmarshal_json_response(components.GetPresetResponse, http_res)
        if utils.match_response(http_res, "400", "application/json"):
            response_data = unmarshal_json_response(
                errors.BadRequestResponseErrorData, http_res
            )
            raise errors.BadRequestResponseError(response_data, http_res)
        if utils.match_response(http_res, "401", "application/json"):
            response_data = unmarshal_json_response(
                errors.UnauthorizedResponseErrorData, http_res
            )
            raise errors.UnauthorizedResponseError(response_data, http_res)
        if utils.match_response(http_res, "404", "application/json"):
            response_data = unmarshal_json_response(
                errors.NotFoundResponseErrorData, http_res
            )
            raise errors.NotFoundResponseError(response_data, http_res)
        if utils.match_response(http_res, "500", "application/json"):
            response_data = unmarshal_json_response(
                errors.InternalServerResponseErrorData, http_res
            )
            raise errors.InternalServerResponseError(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.OpenRouterDefaultError(
                "API error occurred", http_res, http_res_text
            )
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.OpenRouterDefaultError(
                "API error occurred", http_res, http_res_text
            )

        raise errors.OpenRouterDefaultError("Unexpected response received", http_res)

    async def get_async(
        self,
        *,
        slug: str,
        http_referer: Optional[str] = None,
        x_open_router_title: Optional[str] = None,
        x_open_router_categories: Optional[str] = None,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> components.GetPresetResponse:
        r"""Get a preset

        Retrieves a preset by its slug with its currently designated version inline.

        :param slug: URL-safe slug identifying the preset.
        :param http_referer: The app identifier should be your app's URL and is used as the primary identifier for rankings.
            This is used to track API usage per application.

        :param x_open_router_title: The app display name allows you to customize how your app appears in OpenRouter's dashboard.

        :param x_open_router_categories: Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.

        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = operations.GetPresetRequest(
            http_referer=http_referer,
            x_open_router_title=x_open_router_title,
            x_open_router_categories=x_open_router_categories,
            slug=slug,
        )

        req = self._build_request_async(
            method="GET",
            path="/presets/{slug}",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=False,
            request_has_path_params=True,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/json",
            http_headers=http_headers,
            _globals=operations.GetPresetGlobals(
                http_referer=self.sdk_configuration.globals.http_referer,
                x_open_router_title=self.sdk_configuration.globals.x_open_router_title,
                x_open_router_categories=self.sdk_configuration.globals.x_open_router_categories,
            ),
            security=self.sdk_configuration.security,
            allow_empty_value=None,
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config
            else:
                retries = utils.RetryConfig(
                    "backoff", utils.BackoffStrategy(500, 60000, 1.5, 3600000), True
                )

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["5XX"])

        http_res = await self.do_request_async(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="getPreset",
                oauth2_scopes=None,
                security_source=get_security_from_env(
                    self.sdk_configuration.security, components.Security
                ),
            ),
            request=req,
            error_status_codes=["400", "401", "404", "4XX", "500", "5XX"],
            retry_config=retry_config,
        )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/json"):
            return unmarshal_json_response(components.GetPresetResponse, http_res)
        if utils.match_response(http_res, "400", "application/json"):
            response_data = unmarshal_json_response(
                errors.BadRequestResponseErrorData, http_res
            )
            raise errors.BadRequestResponseError(response_data, http_res)
        if utils.match_response(http_res, "401", "application/json"):
            response_data = unmarshal_json_response(
                errors.UnauthorizedResponseErrorData, http_res
            )
            raise errors.UnauthorizedResponseError(response_data, http_res)
        if utils.match_response(http_res, "404", "application/json"):
            response_data = unmarshal_json_response(
                errors.NotFoundResponseErrorData, http_res
            )
            raise errors.NotFoundResponseError(response_data, http_res)
        if utils.match_response(http_res, "500", "application/json"):
            response_data = unmarshal_json_response(
                errors.InternalServerResponseErrorData, http_res
            )
            raise errors.InternalServerResponseError(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.OpenRouterDefaultError(
                "API error occurred", http_res, http_res_text
            )
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.OpenRouterDefaultError(
                "API error occurred", http_res, http_res_text
            )

        raise errors.OpenRouterDefaultError("Unexpected response received", http_res)

    def create_presets_chat_completions(
        self,
        *,
        slug: str,
        messages: Union[
            List[components.ChatMessages], List[components.ChatMessagesTypedDict]
        ],
        http_referer: Optional[str] = None,
        x_open_router_title: Optional[str] = None,
        x_open_router_categories: Optional[str] = None,
        cache_control: Optional[
            Union[
                components.AnthropicCacheControlDirective,
                components.AnthropicCacheControlDirectiveTypedDict,
            ]
        ] = None,
        debug: Optional[
            Union[components.ChatDebugOptions, components.ChatDebugOptionsTypedDict]
        ] = None,
        frequency_penalty: OptionalNullable[float] = UNSET,
        image_config: Optional[
            Union[
                Dict[str, components.ImageConfig],
                Dict[str, components.ImageConfigTypedDict],
            ]
        ] = None,
        logit_bias: OptionalNullable[Dict[str, float]] = UNSET,
        logprobs: OptionalNullable[bool] = UNSET,
        max_completion_tokens: OptionalNullable[int] = UNSET,
        max_tokens: OptionalNullable[int] = UNSET,
        metadata: Optional[Dict[str, str]] = None,
        min_p: OptionalNullable[float] = UNSET,
        modalities: Optional[List[components.Modality]] = None,
        model: Optional[str] = None,
        models: Optional[List[str]] = None,
        parallel_tool_calls: OptionalNullable[bool] = UNSET,
        plugins: Optional[
            Union[
                List[components.ChatRequestPlugin],
                List[components.ChatRequestPluginTypedDict],
            ]
        ] = None,
        presence_penalty: OptionalNullable[float] = UNSET,
        provider: OptionalNullable[
            Union[
                components.ProviderPreferences, components.ProviderPreferencesTypedDict
            ]
        ] = UNSET,
        reasoning: Optional[
            Union[
                components.ChatRequestReasoning,
                components.ChatRequestReasoningTypedDict,
            ]
        ] = None,
        reasoning_effort: OptionalNullable[
            components.ChatRequestReasoningEffort
        ] = UNSET,
        repetition_penalty: OptionalNullable[float] = UNSET,
        response_format: Optional[
            Union[components.ResponseFormat, components.ResponseFormatTypedDict]
        ] = None,
        seed: OptionalNullable[int] = UNSET,
        service_tier: OptionalNullable[components.ChatRequestServiceTier] = UNSET,
        session_id: Optional[str] = None,
        stop: OptionalNullable[
            Union[components.Stop, components.StopTypedDict]
        ] = UNSET,
        stop_server_tools_when: Optional[
            Union[
                List[components.StopServerToolsWhenCondition],
                List[components.StopServerToolsWhenConditionTypedDict],
            ]
        ] = None,
        stream: Optional[bool] = False,
        stream_options: OptionalNullable[
            Union[components.ChatStreamOptions, components.ChatStreamOptionsTypedDict]
        ] = UNSET,
        temperature: OptionalNullable[float] = UNSET,
        tool_choice: Optional[
            Union[components.ChatToolChoice, components.ChatToolChoiceTypedDict]
        ] = None,
        tools: Optional[
            Union[
                List[components.ChatFunctionTool],
                List[components.ChatFunctionToolTypedDict],
            ]
        ] = None,
        top_a: OptionalNullable[float] = UNSET,
        top_k: OptionalNullable[int] = UNSET,
        top_logprobs: OptionalNullable[int] = UNSET,
        top_p: OptionalNullable[float] = UNSET,
        trace: Optional[
            Union[components.TraceConfig, components.TraceConfigTypedDict]
        ] = None,
        user: Optional[str] = None,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> components.CreatePresetFromInferenceResponse:
        r"""Create a preset from a chat-completions request body

        Creates a preset (or a new version of an existing one) from an inference request body. Only fields that overlap with the preset config are persisted; other fields (e.g. `messages`, `stream`, `prompt`) are silently ignored.

        :param slug: URL-safe slug identifying the preset. Created if it does not exist.
        :param messages: List of messages for the conversation
        :param http_referer: The app identifier should be your app's URL and is used as the primary identifier for rankings.
            This is used to track API usage per application.

        :param x_open_router_title: The app display name allows you to customize how your app appears in OpenRouter's dashboard.

        :param x_open_router_categories: Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.

        :param cache_control: Enable automatic prompt caching. When set at the top level, the system automatically applies cache breakpoints to the last cacheable block in the request. Currently supported for Anthropic Claude models.
        :param debug: Debug options for inspecting request transformations (streaming only)
        :param frequency_penalty: Frequency penalty (-2.0 to 2.0)
        :param image_config: Provider-specific image configuration options. Keys and values vary by model/provider. See https://openrouter.ai/docs/guides/overview/multimodal/image-generation for more details.
        :param logit_bias: Token logit bias adjustments
        :param logprobs: Return log probabilities
        :param max_completion_tokens: Maximum tokens in completion
        :param max_tokens: Maximum tokens (deprecated, use max_completion_tokens). Note: some providers enforce a minimum of 16.
        :param metadata: Key-value pairs for additional object information (max 16 pairs, 64 char keys, 512 char values)
        :param min_p: Minimum probability threshold relative to the most likely token. Tokens with probability below min_p * (probability of top token) are filtered out. Not all providers support this parameter.
        :param modalities: Output modalities for the response. Supported values are \"text\", \"image\", and \"audio\".
        :param model: Model to use for completion
        :param models: Models to use for completion
        :param parallel_tool_calls: Whether to enable parallel function calling during tool use. When true, the model may generate multiple tool calls in a single response.
        :param plugins: Plugins you want to enable for this request, including their settings.
        :param presence_penalty: Presence penalty (-2.0 to 2.0)
        :param provider: When multiple model providers are available, optionally indicate your routing preference.
        :param reasoning: Configuration options for reasoning models
        :param reasoning_effort: Shorthand for setting reasoning effort. Equivalent to setting reasoning.effort. Cannot be used simultaneously with reasoning.effort if they differ.
        :param repetition_penalty: Penalizes tokens based on how much they have already appeared in the text. A value of 1.0 means no penalty. Values above 1.0 penalize repeated tokens more strongly. Not all providers support this parameter.
        :param response_format: Response format configuration
        :param seed: Random seed for deterministic outputs
        :param service_tier: The service tier to use for processing this request.
        :param session_id: A unique identifier for grouping related requests (e.g., a conversation or agent workflow). When provided, OpenRouter uses it as the sticky routing key, routing all requests in the session to the same provider to maximize prompt cache hits. Also used for observability grouping. If provided in both the request body and the x-session-id header, the body value takes precedence. Maximum of 256 characters.
        :param stop: Stop sequences (up to 4)
        :param stop_server_tools_when: Stop conditions for the server-tool agent loop. Any condition firing halts the loop (OR logic). When set, this overrides `max_tool_calls`.
        :param stream: Enable streaming response
        :param stream_options: Streaming configuration options
        :param temperature: Sampling temperature (0-2)
        :param tool_choice: Tool choice configuration
        :param tools: Available tools for function calling
        :param top_a: Consider only tokens with \"sufficiently high\" probabilities based on the probability of the most likely token. Not all providers support this parameter.
        :param top_k: Limits the model to choose from the top K most likely tokens at each step. A value of 1 means the model will always pick the most likely next token. Not all providers support this parameter.
        :param top_logprobs: Number of top log probabilities to return (0-20)
        :param top_p: Nucleus sampling parameter (0-1)
        :param trace: Metadata for observability and tracing. Known keys (trace_id, trace_name, span_name, generation_name, parent_span_id) have special handling. Additional keys are passed through as custom metadata to configured broadcast destinations.
        :param user: Unique user identifier
        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = operations.CreatePresetsChatCompletionsRequest(
            http_referer=http_referer,
            x_open_router_title=x_open_router_title,
            x_open_router_categories=x_open_router_categories,
            slug=slug,
            chat_request=components.ChatRequest(
                cache_control=utils.get_pydantic_model(
                    cache_control, Optional[components.AnthropicCacheControlDirective]
                ),
                debug=utils.get_pydantic_model(
                    debug, Optional[components.ChatDebugOptions]
                ),
                frequency_penalty=frequency_penalty,
                image_config=image_config,
                logit_bias=logit_bias,
                logprobs=logprobs,
                max_completion_tokens=max_completion_tokens,
                max_tokens=max_tokens,
                messages=utils.get_pydantic_model(
                    messages, List[components.ChatMessages]
                ),
                metadata=metadata,
                min_p=min_p,
                modalities=modalities,
                model=model,
                models=models,
                parallel_tool_calls=parallel_tool_calls,
                plugins=utils.get_pydantic_model(
                    plugins, Optional[List[components.ChatRequestPlugin]]
                ),
                presence_penalty=presence_penalty,
                provider=utils.get_pydantic_model(
                    provider, OptionalNullable[components.ProviderPreferences]
                ),
                reasoning=utils.get_pydantic_model(
                    reasoning, Optional[components.ChatRequestReasoning]
                ),
                reasoning_effort=reasoning_effort,
                repetition_penalty=repetition_penalty,
                response_format=utils.get_pydantic_model(
                    response_format, Optional[components.ResponseFormat]
                ),
                seed=seed,
                service_tier=service_tier,
                session_id=session_id,
                stop=stop,
                stop_server_tools_when=utils.get_pydantic_model(
                    stop_server_tools_when,
                    Optional[List[components.StopServerToolsWhenCondition]],
                ),
                stream=stream,
                stream_options=utils.get_pydantic_model(
                    stream_options, OptionalNullable[components.ChatStreamOptions]
                ),
                temperature=temperature,
                tool_choice=utils.get_pydantic_model(
                    tool_choice, Optional[components.ChatToolChoice]
                ),
                tools=utils.get_pydantic_model(
                    tools, Optional[List[components.ChatFunctionTool]]
                ),
                top_a=top_a,
                top_k=top_k,
                top_logprobs=top_logprobs,
                top_p=top_p,
                trace=utils.get_pydantic_model(trace, Optional[components.TraceConfig]),
                user=user,
            ),
        )

        req = self._build_request(
            method="POST",
            path="/presets/{slug}/chat/completions",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=True,
            request_has_path_params=True,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/json",
            http_headers=http_headers,
            _globals=operations.CreatePresetsChatCompletionsGlobals(
                http_referer=self.sdk_configuration.globals.http_referer,
                x_open_router_title=self.sdk_configuration.globals.x_open_router_title,
                x_open_router_categories=self.sdk_configuration.globals.x_open_router_categories,
            ),
            security=self.sdk_configuration.security,
            get_serialized_body=lambda: utils.serialize_request_body(
                request.chat_request, False, False, "json", components.ChatRequest
            ),
            allow_empty_value=None,
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config
            else:
                retries = utils.RetryConfig(
                    "backoff", utils.BackoffStrategy(500, 60000, 1.5, 3600000), True
                )

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["5XX"])

        http_res = self.do_request(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="createPresetsChatCompletions",
                oauth2_scopes=None,
                security_source=get_security_from_env(
                    self.sdk_configuration.security, components.Security
                ),
            ),
            request=req,
            error_status_codes=["400", "401", "403", "404", "409", "4XX", "500", "5XX"],
            retry_config=retry_config,
        )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/json"):
            return unmarshal_json_response(
                components.CreatePresetFromInferenceResponse, http_res
            )
        if utils.match_response(http_res, "400", "application/json"):
            response_data = unmarshal_json_response(
                errors.BadRequestResponseErrorData, http_res
            )
            raise errors.BadRequestResponseError(response_data, http_res)
        if utils.match_response(http_res, "401", "application/json"):
            response_data = unmarshal_json_response(
                errors.UnauthorizedResponseErrorData, http_res
            )
            raise errors.UnauthorizedResponseError(response_data, http_res)
        if utils.match_response(http_res, "403", "application/json"):
            response_data = unmarshal_json_response(
                errors.ForbiddenResponseErrorData, http_res
            )
            raise errors.ForbiddenResponseError(response_data, http_res)
        if utils.match_response(http_res, "404", "application/json"):
            response_data = unmarshal_json_response(
                errors.NotFoundResponseErrorData, http_res
            )
            raise errors.NotFoundResponseError(response_data, http_res)
        if utils.match_response(http_res, "409", "application/json"):
            response_data = unmarshal_json_response(
                errors.ConflictResponseErrorData, http_res
            )
            raise errors.ConflictResponseError(response_data, http_res)
        if utils.match_response(http_res, "500", "application/json"):
            response_data = unmarshal_json_response(
                errors.InternalServerResponseErrorData, http_res
            )
            raise errors.InternalServerResponseError(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.OpenRouterDefaultError(
                "API error occurred", http_res, http_res_text
            )
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.OpenRouterDefaultError(
                "API error occurred", http_res, http_res_text
            )

        raise errors.OpenRouterDefaultError("Unexpected response received", http_res)

    async def create_presets_chat_completions_async(
        self,
        *,
        slug: str,
        messages: Union[
            List[components.ChatMessages], List[components.ChatMessagesTypedDict]
        ],
        http_referer: Optional[str] = None,
        x_open_router_title: Optional[str] = None,
        x_open_router_categories: Optional[str] = None,
        cache_control: Optional[
            Union[
                components.AnthropicCacheControlDirective,
                components.AnthropicCacheControlDirectiveTypedDict,
            ]
        ] = None,
        debug: Optional[
            Union[components.ChatDebugOptions, components.ChatDebugOptionsTypedDict]
        ] = None,
        frequency_penalty: OptionalNullable[float] = UNSET,
        image_config: Optional[
            Union[
                Dict[str, components.ImageConfig],
                Dict[str, components.ImageConfigTypedDict],
            ]
        ] = None,
        logit_bias: OptionalNullable[Dict[str, float]] = UNSET,
        logprobs: OptionalNullable[bool] = UNSET,
        max_completion_tokens: OptionalNullable[int] = UNSET,
        max_tokens: OptionalNullable[int] = UNSET,
        metadata: Optional[Dict[str, str]] = None,
        min_p: OptionalNullable[float] = UNSET,
        modalities: Optional[List[components.Modality]] = None,
        model: Optional[str] = None,
        models: Optional[List[str]] = None,
        parallel_tool_calls: OptionalNullable[bool] = UNSET,
        plugins: Optional[
            Union[
                List[components.ChatRequestPlugin],
                List[components.ChatRequestPluginTypedDict],
            ]
        ] = None,
        presence_penalty: OptionalNullable[float] = UNSET,
        provider: OptionalNullable[
            Union[
                components.ProviderPreferences, components.ProviderPreferencesTypedDict
            ]
        ] = UNSET,
        reasoning: Optional[
            Union[
                components.ChatRequestReasoning,
                components.ChatRequestReasoningTypedDict,
            ]
        ] = None,
        reasoning_effort: OptionalNullable[
            components.ChatRequestReasoningEffort
        ] = UNSET,
        repetition_penalty: OptionalNullable[float] = UNSET,
        response_format: Optional[
            Union[components.ResponseFormat, components.ResponseFormatTypedDict]
        ] = None,
        seed: OptionalNullable[int] = UNSET,
        service_tier: OptionalNullable[components.ChatRequestServiceTier] = UNSET,
        session_id: Optional[str] = None,
        stop: OptionalNullable[
            Union[components.Stop, components.StopTypedDict]
        ] = UNSET,
        stop_server_tools_when: Optional[
            Union[
                List[components.StopServerToolsWhenCondition],
                List[components.StopServerToolsWhenConditionTypedDict],
            ]
        ] = None,
        stream: Optional[bool] = False,
        stream_options: OptionalNullable[
            Union[components.ChatStreamOptions, components.ChatStreamOptionsTypedDict]
        ] = UNSET,
        temperature: OptionalNullable[float] = UNSET,
        tool_choice: Optional[
            Union[components.ChatToolChoice, components.ChatToolChoiceTypedDict]
        ] = None,
        tools: Optional[
            Union[
                List[components.ChatFunctionTool],
                List[components.ChatFunctionToolTypedDict],
            ]
        ] = None,
        top_a: OptionalNullable[float] = UNSET,
        top_k: OptionalNullable[int] = UNSET,
        top_logprobs: OptionalNullable[int] = UNSET,
        top_p: OptionalNullable[float] = UNSET,
        trace: Optional[
            Union[components.TraceConfig, components.TraceConfigTypedDict]
        ] = None,
        user: Optional[str] = None,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> components.CreatePresetFromInferenceResponse:
        r"""Create a preset from a chat-completions request body

        Creates a preset (or a new version of an existing one) from an inference request body. Only fields that overlap with the preset config are persisted; other fields (e.g. `messages`, `stream`, `prompt`) are silently ignored.

        :param slug: URL-safe slug identifying the preset. Created if it does not exist.
        :param messages: List of messages for the conversation
        :param http_referer: The app identifier should be your app's URL and is used as the primary identifier for rankings.
            This is used to track API usage per application.

        :param x_open_router_title: The app display name allows you to customize how your app appears in OpenRouter's dashboard.

        :param x_open_router_categories: Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.

        :param cache_control: Enable automatic prompt caching. When set at the top level, the system automatically applies cache breakpoints to the last cacheable block in the request. Currently supported for Anthropic Claude models.
        :param debug: Debug options for inspecting request transformations (streaming only)
        :param frequency_penalty: Frequency penalty (-2.0 to 2.0)
        :param image_config: Provider-specific image configuration options. Keys and values vary by model/provider. See https://openrouter.ai/docs/guides/overview/multimodal/image-generation for more details.
        :param logit_bias: Token logit bias adjustments
        :param logprobs: Return log probabilities
        :param max_completion_tokens: Maximum tokens in completion
        :param max_tokens: Maximum tokens (deprecated, use max_completion_tokens). Note: some providers enforce a minimum of 16.
        :param metadata: Key-value pairs for additional object information (max 16 pairs, 64 char keys, 512 char values)
        :param min_p: Minimum probability threshold relative to the most likely token. Tokens with probability below min_p * (probability of top token) are filtered out. Not all providers support this parameter.
        :param modalities: Output modalities for the response. Supported values are \"text\", \"image\", and \"audio\".
        :param model: Model to use for completion
        :param models: Models to use for completion
        :param parallel_tool_calls: Whether to enable parallel function calling during tool use. When true, the model may generate multiple tool calls in a single response.
        :param plugins: Plugins you want to enable for this request, including their settings.
        :param presence_penalty: Presence penalty (-2.0 to 2.0)
        :param provider: When multiple model providers are available, optionally indicate your routing preference.
        :param reasoning: Configuration options for reasoning models
        :param reasoning_effort: Shorthand for setting reasoning effort. Equivalent to setting reasoning.effort. Cannot be used simultaneously with reasoning.effort if they differ.
        :param repetition_penalty: Penalizes tokens based on how much they have already appeared in the text. A value of 1.0 means no penalty. Values above 1.0 penalize repeated tokens more strongly. Not all providers support this parameter.
        :param response_format: Response format configuration
        :param seed: Random seed for deterministic outputs
        :param service_tier: The service tier to use for processing this request.
        :param session_id: A unique identifier for grouping related requests (e.g., a conversation or agent workflow). When provided, OpenRouter uses it as the sticky routing key, routing all requests in the session to the same provider to maximize prompt cache hits. Also used for observability grouping. If provided in both the request body and the x-session-id header, the body value takes precedence. Maximum of 256 characters.
        :param stop: Stop sequences (up to 4)
        :param stop_server_tools_when: Stop conditions for the server-tool agent loop. Any condition firing halts the loop (OR logic). When set, this overrides `max_tool_calls`.
        :param stream: Enable streaming response
        :param stream_options: Streaming configuration options
        :param temperature: Sampling temperature (0-2)
        :param tool_choice: Tool choice configuration
        :param tools: Available tools for function calling
        :param top_a: Consider only tokens with \"sufficiently high\" probabilities based on the probability of the most likely token. Not all providers support this parameter.
        :param top_k: Limits the model to choose from the top K most likely tokens at each step. A value of 1 means the model will always pick the most likely next token. Not all providers support this parameter.
        :param top_logprobs: Number of top log probabilities to return (0-20)
        :param top_p: Nucleus sampling parameter (0-1)
        :param trace: Metadata for observability and tracing. Known keys (trace_id, trace_name, span_name, generation_name, parent_span_id) have special handling. Additional keys are passed through as custom metadata to configured broadcast destinations.
        :param user: Unique user identifier
        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = operations.CreatePresetsChatCompletionsRequest(
            http_referer=http_referer,
            x_open_router_title=x_open_router_title,
            x_open_router_categories=x_open_router_categories,
            slug=slug,
            chat_request=components.ChatRequest(
                cache_control=utils.get_pydantic_model(
                    cache_control, Optional[components.AnthropicCacheControlDirective]
                ),
                debug=utils.get_pydantic_model(
                    debug, Optional[components.ChatDebugOptions]
                ),
                frequency_penalty=frequency_penalty,
                image_config=image_config,
                logit_bias=logit_bias,
                logprobs=logprobs,
                max_completion_tokens=max_completion_tokens,
                max_tokens=max_tokens,
                messages=utils.get_pydantic_model(
                    messages, List[components.ChatMessages]
                ),
                metadata=metadata,
                min_p=min_p,
                modalities=modalities,
                model=model,
                models=models,
                parallel_tool_calls=parallel_tool_calls,
                plugins=utils.get_pydantic_model(
                    plugins, Optional[List[components.ChatRequestPlugin]]
                ),
                presence_penalty=presence_penalty,
                provider=utils.get_pydantic_model(
                    provider, OptionalNullable[components.ProviderPreferences]
                ),
                reasoning=utils.get_pydantic_model(
                    reasoning, Optional[components.ChatRequestReasoning]
                ),
                reasoning_effort=reasoning_effort,
                repetition_penalty=repetition_penalty,
                response_format=utils.get_pydantic_model(
                    response_format, Optional[components.ResponseFormat]
                ),
                seed=seed,
                service_tier=service_tier,
                session_id=session_id,
                stop=stop,
                stop_server_tools_when=utils.get_pydantic_model(
                    stop_server_tools_when,
                    Optional[List[components.StopServerToolsWhenCondition]],
                ),
                stream=stream,
                stream_options=utils.get_pydantic_model(
                    stream_options, OptionalNullable[components.ChatStreamOptions]
                ),
                temperature=temperature,
                tool_choice=utils.get_pydantic_model(
                    tool_choice, Optional[components.ChatToolChoice]
                ),
                tools=utils.get_pydantic_model(
                    tools, Optional[List[components.ChatFunctionTool]]
                ),
                top_a=top_a,
                top_k=top_k,
                top_logprobs=top_logprobs,
                top_p=top_p,
                trace=utils.get_pydantic_model(trace, Optional[components.TraceConfig]),
                user=user,
            ),
        )

        req = self._build_request_async(
            method="POST",
            path="/presets/{slug}/chat/completions",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=True,
            request_has_path_params=True,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/json",
            http_headers=http_headers,
            _globals=operations.CreatePresetsChatCompletionsGlobals(
                http_referer=self.sdk_configuration.globals.http_referer,
                x_open_router_title=self.sdk_configuration.globals.x_open_router_title,
                x_open_router_categories=self.sdk_configuration.globals.x_open_router_categories,
            ),
            security=self.sdk_configuration.security,
            get_serialized_body=lambda: utils.serialize_request_body(
                request.chat_request, False, False, "json", components.ChatRequest
            ),
            allow_empty_value=None,
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config
            else:
                retries = utils.RetryConfig(
                    "backoff", utils.BackoffStrategy(500, 60000, 1.5, 3600000), True
                )

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["5XX"])

        http_res = await self.do_request_async(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="createPresetsChatCompletions",
                oauth2_scopes=None,
                security_source=get_security_from_env(
                    self.sdk_configuration.security, components.Security
                ),
            ),
            request=req,
            error_status_codes=["400", "401", "403", "404", "409", "4XX", "500", "5XX"],
            retry_config=retry_config,
        )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/json"):
            return unmarshal_json_response(
                components.CreatePresetFromInferenceResponse, http_res
            )
        if utils.match_response(http_res, "400", "application/json"):
            response_data = unmarshal_json_response(
                errors.BadRequestResponseErrorData, http_res
            )
            raise errors.BadRequestResponseError(response_data, http_res)
        if utils.match_response(http_res, "401", "application/json"):
            response_data = unmarshal_json_response(
                errors.UnauthorizedResponseErrorData, http_res
            )
            raise errors.UnauthorizedResponseError(response_data, http_res)
        if utils.match_response(http_res, "403", "application/json"):
            response_data = unmarshal_json_response(
                errors.ForbiddenResponseErrorData, http_res
            )
            raise errors.ForbiddenResponseError(response_data, http_res)
        if utils.match_response(http_res, "404", "application/json"):
            response_data = unmarshal_json_response(
                errors.NotFoundResponseErrorData, http_res
            )
            raise errors.NotFoundResponseError(response_data, http_res)
        if utils.match_response(http_res, "409", "application/json"):
            response_data = unmarshal_json_response(
                errors.ConflictResponseErrorData, http_res
            )
            raise errors.ConflictResponseError(response_data, http_res)
        if utils.match_response(http_res, "500", "application/json"):
            response_data = unmarshal_json_response(
                errors.InternalServerResponseErrorData, http_res
            )
            raise errors.InternalServerResponseError(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.OpenRouterDefaultError(
                "API error occurred", http_res, http_res_text
            )
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.OpenRouterDefaultError(
                "API error occurred", http_res, http_res_text
            )

        raise errors.OpenRouterDefaultError("Unexpected response received", http_res)

    def create_presets_messages(
        self,
        *,
        slug: str,
        messages: Nullable[
            Union[
                List[components.MessagesMessageParam],
                List[components.MessagesMessageParamTypedDict],
            ]
        ],
        model: str,
        http_referer: Optional[str] = None,
        x_open_router_title: Optional[str] = None,
        x_open_router_categories: Optional[str] = None,
        cache_control: Optional[
            Union[
                components.AnthropicCacheControlDirective,
                components.AnthropicCacheControlDirectiveTypedDict,
            ]
        ] = None,
        context_management: OptionalNullable[
            Union[components.ContextManagement, components.ContextManagementTypedDict]
        ] = UNSET,
        fallbacks: OptionalNullable[
            Union[
                List[components.MessagesFallbackParam],
                List[components.MessagesFallbackParamTypedDict],
            ]
        ] = UNSET,
        max_tokens: Optional[int] = None,
        metadata: Optional[
            Union[components.Metadata, components.MetadataTypedDict]
        ] = None,
        models: Optional[List[str]] = None,
        output_config: Optional[
            Union[
                components.MessagesOutputConfig,
                components.MessagesOutputConfigTypedDict,
            ]
        ] = None,
        plugins: Optional[
            Union[
                List[components.MessagesRequestPlugin],
                List[components.MessagesRequestPluginTypedDict],
            ]
        ] = None,
        provider: OptionalNullable[
            Union[
                components.ProviderPreferences, components.ProviderPreferencesTypedDict
            ]
        ] = UNSET,
        service_tier: Optional[str] = None,
        session_id: Optional[str] = None,
        speed: OptionalNullable[components.Speed] = UNSET,
        stop_sequences: Optional[List[str]] = None,
        stop_server_tools_when: Optional[
            Union[
                List[components.StopServerToolsWhenCondition],
                List[components.StopServerToolsWhenConditionTypedDict],
            ]
        ] = None,
        stream: Optional[bool] = None,
        system: Optional[Union[components.System, components.SystemTypedDict]] = None,
        temperature: Optional[float] = None,
        thinking: Optional[
            Union[components.Thinking, components.ThinkingTypedDict]
        ] = None,
        tool_choice: Optional[
            Union[components.ToolChoice, components.ToolChoiceTypedDict]
        ] = None,
        tools: Optional[
            Union[
                List[components.MessagesRequestToolUnion],
                List[components.MessagesRequestToolUnionTypedDict],
            ]
        ] = None,
        top_k: Optional[int] = None,
        top_p: Optional[float] = None,
        trace: Optional[
            Union[components.TraceConfig, components.TraceConfigTypedDict]
        ] = None,
        user: Optional[str] = None,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> components.CreatePresetFromInferenceResponse:
        r"""Create a preset from a messages request body

        Creates a preset (or a new version of an existing one) from an inference request body. Only fields that overlap with the preset config are persisted; other fields (e.g. `messages`, `stream`, `prompt`) are silently ignored.

        :param slug: URL-safe slug identifying the preset. Created if it does not exist.
        :param messages:
        :param model:
        :param http_referer: The app identifier should be your app's URL and is used as the primary identifier for rankings.
            This is used to track API usage per application.

        :param x_open_router_title: The app display name allows you to customize how your app appears in OpenRouter's dashboard.

        :param x_open_router_categories: Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.

        :param cache_control: Enable automatic prompt caching. When set at the top level, the system automatically applies cache breakpoints to the last cacheable block in the request. Currently supported for Anthropic Claude models.
        :param context_management:
        :param fallbacks: Fallback models to try if the primary model fails or refuses, in order. Handled by OpenRouter multi-model routing rather than Anthropic server-side fallbacks; cannot be combined with `models`. Each entry accepts only `model`. Maximum of 3 entries.
        :param max_tokens:
        :param metadata:
        :param models:
        :param output_config: Configuration for controlling output behavior. Supports the effort parameter and structured output format.
        :param plugins: Plugins you want to enable for this request, including their settings.
        :param provider: When multiple model providers are available, optionally indicate your routing preference.
        :param service_tier:
        :param session_id: A unique identifier for grouping related requests (e.g., a conversation or agent workflow). When provided, OpenRouter uses it as the sticky routing key, routing all requests in the session to the same provider to maximize prompt cache hits. Also used for observability grouping. If provided in both the request body and the x-session-id header, the body value takes precedence. Maximum of 256 characters.
        :param speed:
        :param stop_sequences:
        :param stop_server_tools_when: Stop conditions for the server-tool agent loop. Any condition firing halts the loop (OR logic). When set, this overrides `max_tool_calls`.
        :param stream:
        :param system:
        :param temperature:
        :param thinking:
        :param tool_choice:
        :param tools:
        :param top_k:
        :param top_p:
        :param trace: Metadata for observability and tracing. Known keys (trace_id, trace_name, span_name, generation_name, parent_span_id) have special handling. Additional keys are passed through as custom metadata to configured broadcast destinations.
        :param user: A unique identifier representing your end-user, which helps distinguish between different users of your app. This allows your app to identify specific users in case of abuse reports, preventing your entire app from being affected by the actions of individual users. Maximum of 256 characters.
        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = operations.CreatePresetsMessagesRequest(
            http_referer=http_referer,
            x_open_router_title=x_open_router_title,
            x_open_router_categories=x_open_router_categories,
            slug=slug,
            messages_request=components.MessagesRequest(
                cache_control=utils.get_pydantic_model(
                    cache_control, Optional[components.AnthropicCacheControlDirective]
                ),
                context_management=utils.get_pydantic_model(
                    context_management, OptionalNullable[components.ContextManagement]
                ),
                fallbacks=utils.get_pydantic_model(
                    fallbacks, OptionalNullable[List[components.MessagesFallbackParam]]
                ),
                max_tokens=max_tokens,
                messages=utils.get_pydantic_model(
                    messages, Nullable[List[components.MessagesMessageParam]]
                ),
                metadata=utils.get_pydantic_model(
                    metadata, Optional[components.Metadata]
                ),
                model=model,
                models=models,
                output_config=utils.get_pydantic_model(
                    output_config, Optional[components.MessagesOutputConfig]
                ),
                plugins=utils.get_pydantic_model(
                    plugins, Optional[List[components.MessagesRequestPlugin]]
                ),
                provider=utils.get_pydantic_model(
                    provider, OptionalNullable[components.ProviderPreferences]
                ),
                service_tier=service_tier,
                session_id=session_id,
                speed=speed,
                stop_sequences=stop_sequences,
                stop_server_tools_when=utils.get_pydantic_model(
                    stop_server_tools_when,
                    Optional[List[components.StopServerToolsWhenCondition]],
                ),
                stream=stream,
                system=utils.get_pydantic_model(system, Optional[components.System]),
                temperature=temperature,
                thinking=utils.get_pydantic_model(
                    thinking, Optional[components.Thinking]
                ),
                tool_choice=utils.get_pydantic_model(
                    tool_choice, Optional[components.ToolChoice]
                ),
                tools=utils.get_pydantic_model(
                    tools, Optional[List[components.MessagesRequestToolUnion]]
                ),
                top_k=top_k,
                top_p=top_p,
                trace=utils.get_pydantic_model(trace, Optional[components.TraceConfig]),
                user=user,
            ),
        )

        req = self._build_request(
            method="POST",
            path="/presets/{slug}/messages",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=True,
            request_has_path_params=True,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/json",
            http_headers=http_headers,
            _globals=operations.CreatePresetsMessagesGlobals(
                http_referer=self.sdk_configuration.globals.http_referer,
                x_open_router_title=self.sdk_configuration.globals.x_open_router_title,
                x_open_router_categories=self.sdk_configuration.globals.x_open_router_categories,
            ),
            security=self.sdk_configuration.security,
            get_serialized_body=lambda: utils.serialize_request_body(
                request.messages_request,
                False,
                False,
                "json",
                components.MessagesRequest,
            ),
            allow_empty_value=None,
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config
            else:
                retries = utils.RetryConfig(
                    "backoff", utils.BackoffStrategy(500, 60000, 1.5, 3600000), True
                )

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["5XX"])

        http_res = self.do_request(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="createPresetsMessages",
                oauth2_scopes=None,
                security_source=get_security_from_env(
                    self.sdk_configuration.security, components.Security
                ),
            ),
            request=req,
            error_status_codes=["400", "401", "403", "404", "409", "4XX", "500", "5XX"],
            retry_config=retry_config,
        )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/json"):
            return unmarshal_json_response(
                components.CreatePresetFromInferenceResponse, http_res
            )
        if utils.match_response(http_res, "400", "application/json"):
            response_data = unmarshal_json_response(
                errors.BadRequestResponseErrorData, http_res
            )
            raise errors.BadRequestResponseError(response_data, http_res)
        if utils.match_response(http_res, "401", "application/json"):
            response_data = unmarshal_json_response(
                errors.UnauthorizedResponseErrorData, http_res
            )
            raise errors.UnauthorizedResponseError(response_data, http_res)
        if utils.match_response(http_res, "403", "application/json"):
            response_data = unmarshal_json_response(
                errors.ForbiddenResponseErrorData, http_res
            )
            raise errors.ForbiddenResponseError(response_data, http_res)
        if utils.match_response(http_res, "404", "application/json"):
            response_data = unmarshal_json_response(
                errors.NotFoundResponseErrorData, http_res
            )
            raise errors.NotFoundResponseError(response_data, http_res)
        if utils.match_response(http_res, "409", "application/json"):
            response_data = unmarshal_json_response(
                errors.ConflictResponseErrorData, http_res
            )
            raise errors.ConflictResponseError(response_data, http_res)
        if utils.match_response(http_res, "500", "application/json"):
            response_data = unmarshal_json_response(
                errors.InternalServerResponseErrorData, http_res
            )
            raise errors.InternalServerResponseError(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.OpenRouterDefaultError(
                "API error occurred", http_res, http_res_text
            )
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.OpenRouterDefaultError(
                "API error occurred", http_res, http_res_text
            )

        raise errors.OpenRouterDefaultError("Unexpected response received", http_res)

    async def create_presets_messages_async(
        self,
        *,
        slug: str,
        messages: Nullable[
            Union[
                List[components.MessagesMessageParam],
                List[components.MessagesMessageParamTypedDict],
            ]
        ],
        model: str,
        http_referer: Optional[str] = None,
        x_open_router_title: Optional[str] = None,
        x_open_router_categories: Optional[str] = None,
        cache_control: Optional[
            Union[
                components.AnthropicCacheControlDirective,
                components.AnthropicCacheControlDirectiveTypedDict,
            ]
        ] = None,
        context_management: OptionalNullable[
            Union[components.ContextManagement, components.ContextManagementTypedDict]
        ] = UNSET,
        fallbacks: OptionalNullable[
            Union[
                List[components.MessagesFallbackParam],
                List[components.MessagesFallbackParamTypedDict],
            ]
        ] = UNSET,
        max_tokens: Optional[int] = None,
        metadata: Optional[
            Union[components.Metadata, components.MetadataTypedDict]
        ] = None,
        models: Optional[List[str]] = None,
        output_config: Optional[
            Union[
                components.MessagesOutputConfig,
                components.MessagesOutputConfigTypedDict,
            ]
        ] = None,
        plugins: Optional[
            Union[
                List[components.MessagesRequestPlugin],
                List[components.MessagesRequestPluginTypedDict],
            ]
        ] = None,
        provider: OptionalNullable[
            Union[
                components.ProviderPreferences, components.ProviderPreferencesTypedDict
            ]
        ] = UNSET,
        service_tier: Optional[str] = None,
        session_id: Optional[str] = None,
        speed: OptionalNullable[components.Speed] = UNSET,
        stop_sequences: Optional[List[str]] = None,
        stop_server_tools_when: Optional[
            Union[
                List[components.StopServerToolsWhenCondition],
                List[components.StopServerToolsWhenConditionTypedDict],
            ]
        ] = None,
        stream: Optional[bool] = None,
        system: Optional[Union[components.System, components.SystemTypedDict]] = None,
        temperature: Optional[float] = None,
        thinking: Optional[
            Union[components.Thinking, components.ThinkingTypedDict]
        ] = None,
        tool_choice: Optional[
            Union[components.ToolChoice, components.ToolChoiceTypedDict]
        ] = None,
        tools: Optional[
            Union[
                List[components.MessagesRequestToolUnion],
                List[components.MessagesRequestToolUnionTypedDict],
            ]
        ] = None,
        top_k: Optional[int] = None,
        top_p: Optional[float] = None,
        trace: Optional[
            Union[components.TraceConfig, components.TraceConfigTypedDict]
        ] = None,
        user: Optional[str] = None,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> components.CreatePresetFromInferenceResponse:
        r"""Create a preset from a messages request body

        Creates a preset (or a new version of an existing one) from an inference request body. Only fields that overlap with the preset config are persisted; other fields (e.g. `messages`, `stream`, `prompt`) are silently ignored.

        :param slug: URL-safe slug identifying the preset. Created if it does not exist.
        :param messages:
        :param model:
        :param http_referer: The app identifier should be your app's URL and is used as the primary identifier for rankings.
            This is used to track API usage per application.

        :param x_open_router_title: The app display name allows you to customize how your app appears in OpenRouter's dashboard.

        :param x_open_router_categories: Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.

        :param cache_control: Enable automatic prompt caching. When set at the top level, the system automatically applies cache breakpoints to the last cacheable block in the request. Currently supported for Anthropic Claude models.
        :param context_management:
        :param fallbacks: Fallback models to try if the primary model fails or refuses, in order. Handled by OpenRouter multi-model routing rather than Anthropic server-side fallbacks; cannot be combined with `models`. Each entry accepts only `model`. Maximum of 3 entries.
        :param max_tokens:
        :param metadata:
        :param models:
        :param output_config: Configuration for controlling output behavior. Supports the effort parameter and structured output format.
        :param plugins: Plugins you want to enable for this request, including their settings.
        :param provider: When multiple model providers are available, optionally indicate your routing preference.
        :param service_tier:
        :param session_id: A unique identifier for grouping related requests (e.g., a conversation or agent workflow). When provided, OpenRouter uses it as the sticky routing key, routing all requests in the session to the same provider to maximize prompt cache hits. Also used for observability grouping. If provided in both the request body and the x-session-id header, the body value takes precedence. Maximum of 256 characters.
        :param speed:
        :param stop_sequences:
        :param stop_server_tools_when: Stop conditions for the server-tool agent loop. Any condition firing halts the loop (OR logic). When set, this overrides `max_tool_calls`.
        :param stream:
        :param system:
        :param temperature:
        :param thinking:
        :param tool_choice:
        :param tools:
        :param top_k:
        :param top_p:
        :param trace: Metadata for observability and tracing. Known keys (trace_id, trace_name, span_name, generation_name, parent_span_id) have special handling. Additional keys are passed through as custom metadata to configured broadcast destinations.
        :param user: A unique identifier representing your end-user, which helps distinguish between different users of your app. This allows your app to identify specific users in case of abuse reports, preventing your entire app from being affected by the actions of individual users. Maximum of 256 characters.
        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = operations.CreatePresetsMessagesRequest(
            http_referer=http_referer,
            x_open_router_title=x_open_router_title,
            x_open_router_categories=x_open_router_categories,
            slug=slug,
            messages_request=components.MessagesRequest(
                cache_control=utils.get_pydantic_model(
                    cache_control, Optional[components.AnthropicCacheControlDirective]
                ),
                context_management=utils.get_pydantic_model(
                    context_management, OptionalNullable[components.ContextManagement]
                ),
                fallbacks=utils.get_pydantic_model(
                    fallbacks, OptionalNullable[List[components.MessagesFallbackParam]]
                ),
                max_tokens=max_tokens,
                messages=utils.get_pydantic_model(
                    messages, Nullable[List[components.MessagesMessageParam]]
                ),
                metadata=utils.get_pydantic_model(
                    metadata, Optional[components.Metadata]
                ),
                model=model,
                models=models,
                output_config=utils.get_pydantic_model(
                    output_config, Optional[components.MessagesOutputConfig]
                ),
                plugins=utils.get_pydantic_model(
                    plugins, Optional[List[components.MessagesRequestPlugin]]
                ),
                provider=utils.get_pydantic_model(
                    provider, OptionalNullable[components.ProviderPreferences]
                ),
                service_tier=service_tier,
                session_id=session_id,
                speed=speed,
                stop_sequences=stop_sequences,
                stop_server_tools_when=utils.get_pydantic_model(
                    stop_server_tools_when,
                    Optional[List[components.StopServerToolsWhenCondition]],
                ),
                stream=stream,
                system=utils.get_pydantic_model(system, Optional[components.System]),
                temperature=temperature,
                thinking=utils.get_pydantic_model(
                    thinking, Optional[components.Thinking]
                ),
                tool_choice=utils.get_pydantic_model(
                    tool_choice, Optional[components.ToolChoice]
                ),
                tools=utils.get_pydantic_model(
                    tools, Optional[List[components.MessagesRequestToolUnion]]
                ),
                top_k=top_k,
                top_p=top_p,
                trace=utils.get_pydantic_model(trace, Optional[components.TraceConfig]),
                user=user,
            ),
        )

        req = self._build_request_async(
            method="POST",
            path="/presets/{slug}/messages",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=True,
            request_has_path_params=True,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/json",
            http_headers=http_headers,
            _globals=operations.CreatePresetsMessagesGlobals(
                http_referer=self.sdk_configuration.globals.http_referer,
                x_open_router_title=self.sdk_configuration.globals.x_open_router_title,
                x_open_router_categories=self.sdk_configuration.globals.x_open_router_categories,
            ),
            security=self.sdk_configuration.security,
            get_serialized_body=lambda: utils.serialize_request_body(
                request.messages_request,
                False,
                False,
                "json",
                components.MessagesRequest,
            ),
            allow_empty_value=None,
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config
            else:
                retries = utils.RetryConfig(
                    "backoff", utils.BackoffStrategy(500, 60000, 1.5, 3600000), True
                )

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["5XX"])

        http_res = await self.do_request_async(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="createPresetsMessages",
                oauth2_scopes=None,
                security_source=get_security_from_env(
                    self.sdk_configuration.security, components.Security
                ),
            ),
            request=req,
            error_status_codes=["400", "401", "403", "404", "409", "4XX", "500", "5XX"],
            retry_config=retry_config,
        )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/json"):
            return unmarshal_json_response(
                components.CreatePresetFromInferenceResponse, http_res
            )
        if utils.match_response(http_res, "400", "application/json"):
            response_data = unmarshal_json_response(
                errors.BadRequestResponseErrorData, http_res
            )
            raise errors.BadRequestResponseError(response_data, http_res)
        if utils.match_response(http_res, "401", "application/json"):
            response_data = unmarshal_json_response(
                errors.UnauthorizedResponseErrorData, http_res
            )
            raise errors.UnauthorizedResponseError(response_data, http_res)
        if utils.match_response(http_res, "403", "application/json"):
            response_data = unmarshal_json_response(
                errors.ForbiddenResponseErrorData, http_res
            )
            raise errors.ForbiddenResponseError(response_data, http_res)
        if utils.match_response(http_res, "404", "application/json"):
            response_data = unmarshal_json_response(
                errors.NotFoundResponseErrorData, http_res
            )
            raise errors.NotFoundResponseError(response_data, http_res)
        if utils.match_response(http_res, "409", "application/json"):
            response_data = unmarshal_json_response(
                errors.ConflictResponseErrorData, http_res
            )
            raise errors.ConflictResponseError(response_data, http_res)
        if utils.match_response(http_res, "500", "application/json"):
            response_data = unmarshal_json_response(
                errors.InternalServerResponseErrorData, http_res
            )
            raise errors.InternalServerResponseError(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.OpenRouterDefaultError(
                "API error occurred", http_res, http_res_text
            )
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.OpenRouterDefaultError(
                "API error occurred", http_res, http_res_text
            )

        raise errors.OpenRouterDefaultError("Unexpected response received", http_res)

    def create_presets_responses(
        self,
        *,
        slug: str,
        http_referer: Optional[str] = None,
        x_open_router_title: Optional[str] = None,
        x_open_router_categories: Optional[str] = None,
        background: OptionalNullable[bool] = UNSET,
        cache_control: Optional[
            Union[
                components.AnthropicCacheControlDirective,
                components.AnthropicCacheControlDirectiveTypedDict,
            ]
        ] = None,
        frequency_penalty: OptionalNullable[float] = UNSET,
        image_config: Optional[
            Union[
                Dict[str, components.ImageConfig],
                Dict[str, components.ImageConfigTypedDict],
            ]
        ] = None,
        include: OptionalNullable[List[components.ResponseIncludesEnum]] = UNSET,
        input: Optional[
            Union[components.InputsUnion, components.InputsUnionTypedDict]
        ] = None,
        instructions: OptionalNullable[str] = UNSET,
        max_output_tokens: OptionalNullable[int] = UNSET,
        max_tool_calls: OptionalNullable[int] = UNSET,
        metadata: OptionalNullable[Dict[str, str]] = UNSET,
        modalities: Optional[List[components.OutputModalityEnum]] = None,
        model: Optional[str] = None,
        models: Optional[List[str]] = None,
        parallel_tool_calls: OptionalNullable[bool] = UNSET,
        plugins: Optional[
            Union[
                List[components.ResponsesRequestPlugin],
                List[components.ResponsesRequestPluginTypedDict],
            ]
        ] = None,
        presence_penalty: OptionalNullable[float] = UNSET,
        previous_response_id: OptionalNullable[str] = UNSET,
        prompt: OptionalNullable[
            Union[
                components.StoredPromptTemplate,
                components.StoredPromptTemplateTypedDict,
            ]
        ] = UNSET,
        prompt_cache_key: OptionalNullable[str] = UNSET,
        provider: OptionalNullable[
            Union[
                components.ProviderPreferences, components.ProviderPreferencesTypedDict
            ]
        ] = UNSET,
        reasoning: OptionalNullable[
            Union[components.ReasoningConfig, components.ReasoningConfigTypedDict]
        ] = UNSET,
        safety_identifier: OptionalNullable[str] = UNSET,
        service_tier: OptionalNullable[components.ResponsesRequestServiceTier] = "auto",
        session_id: Optional[str] = None,
        stop_server_tools_when: Optional[
            Union[
                List[components.StopServerToolsWhenCondition],
                List[components.StopServerToolsWhenConditionTypedDict],
            ]
        ] = None,
        stream: Optional[bool] = False,
        temperature: OptionalNullable[float] = UNSET,
        text: Optional[
            Union[components.TextExtendedConfig, components.TextExtendedConfigTypedDict]
        ] = None,
        tool_choice: Optional[
            Union[
                components.OpenAIResponsesToolChoiceUnion,
                components.OpenAIResponsesToolChoiceUnionTypedDict,
            ]
        ] = None,
        tools: Optional[
            Union[
                List[components.ResponsesRequestToolUnion],
                List[components.ResponsesRequestToolUnionTypedDict],
            ]
        ] = None,
        top_k: Optional[int] = None,
        top_logprobs: OptionalNullable[int] = UNSET,
        top_p: OptionalNullable[float] = UNSET,
        trace: Optional[
            Union[components.TraceConfig, components.TraceConfigTypedDict]
        ] = None,
        truncation: OptionalNullable[components.OpenAIResponsesTruncation] = UNSET,
        user: Optional[str] = None,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> components.CreatePresetFromInferenceResponse:
        r"""Create a preset from a responses request body

        Creates a preset (or a new version of an existing one) from an inference request body. Only fields that overlap with the preset config are persisted; other fields (e.g. `messages`, `stream`, `prompt`) are silently ignored.

        :param slug: URL-safe slug identifying the preset. Created if it does not exist.
        :param http_referer: The app identifier should be your app's URL and is used as the primary identifier for rankings.
            This is used to track API usage per application.

        :param x_open_router_title: The app display name allows you to customize how your app appears in OpenRouter's dashboard.

        :param x_open_router_categories: Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.

        :param background:
        :param cache_control: Enable automatic prompt caching. When set at the top level, the system automatically applies cache breakpoints to the last cacheable block in the request. Currently supported for Anthropic Claude models.
        :param frequency_penalty:
        :param image_config: Provider-specific image configuration options. Keys and values vary by model/provider. See https://openrouter.ai/docs/guides/overview/multimodal/image-generation for more details.
        :param include:
        :param input: Input for a response request - can be a string or array of items
        :param instructions:
        :param max_output_tokens:
        :param max_tool_calls:
        :param metadata: Metadata key-value pairs for the request. Keys must be ≤64 characters and cannot contain brackets. Values must be ≤512 characters. Maximum 16 pairs allowed.
        :param modalities: Output modalities for the response. Supported values are \"text\" and \"image\".
        :param model:
        :param models:
        :param parallel_tool_calls:
        :param plugins: Plugins you want to enable for this request, including their settings.
        :param presence_penalty:
        :param previous_response_id:
        :param prompt:
        :param prompt_cache_key:
        :param provider: When multiple model providers are available, optionally indicate your routing preference.
        :param reasoning: Configuration for reasoning mode in the response
        :param safety_identifier:
        :param service_tier:
        :param session_id: A unique identifier for grouping related requests (e.g., a conversation or agent workflow). When provided, OpenRouter uses it as the sticky routing key, routing all requests in the session to the same provider to maximize prompt cache hits. Also used for observability grouping. If provided in both the request body and the x-session-id header, the body value takes precedence. Maximum of 256 characters.
        :param stop_server_tools_when: Stop conditions for the server-tool agent loop. Any condition firing halts the loop (OR logic). When set, this overrides `max_tool_calls`.
        :param stream:
        :param temperature:
        :param text: Text output configuration including format and verbosity
        :param tool_choice:
        :param tools:
        :param top_k:
        :param top_logprobs:
        :param top_p:
        :param trace: Metadata for observability and tracing. Known keys (trace_id, trace_name, span_name, generation_name, parent_span_id) have special handling. Additional keys are passed through as custom metadata to configured broadcast destinations.
        :param truncation:
        :param user: A unique identifier representing your end-user, which helps distinguish between different users of your app. This allows your app to identify specific users in case of abuse reports, preventing your entire app from being affected by the actions of individual users. Maximum of 256 characters.
        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = operations.CreatePresetsResponsesRequest(
            http_referer=http_referer,
            x_open_router_title=x_open_router_title,
            x_open_router_categories=x_open_router_categories,
            slug=slug,
            responses_request=components.ResponsesRequest(
                background=background,
                cache_control=utils.get_pydantic_model(
                    cache_control, Optional[components.AnthropicCacheControlDirective]
                ),
                frequency_penalty=frequency_penalty,
                image_config=image_config,
                include=include,
                input=utils.get_pydantic_model(input, Optional[components.InputsUnion]),
                instructions=instructions,
                max_output_tokens=max_output_tokens,
                max_tool_calls=max_tool_calls,
                metadata=metadata,
                modalities=modalities,
                model=model,
                models=models,
                parallel_tool_calls=parallel_tool_calls,
                plugins=utils.get_pydantic_model(
                    plugins, Optional[List[components.ResponsesRequestPlugin]]
                ),
                presence_penalty=presence_penalty,
                previous_response_id=previous_response_id,
                prompt=utils.get_pydantic_model(
                    prompt, OptionalNullable[components.StoredPromptTemplate]
                ),
                prompt_cache_key=prompt_cache_key,
                provider=utils.get_pydantic_model(
                    provider, OptionalNullable[components.ProviderPreferences]
                ),
                reasoning=utils.get_pydantic_model(
                    reasoning, OptionalNullable[components.ReasoningConfig]
                ),
                safety_identifier=safety_identifier,
                service_tier=service_tier,
                session_id=session_id,
                stop_server_tools_when=utils.get_pydantic_model(
                    stop_server_tools_when,
                    Optional[List[components.StopServerToolsWhenCondition]],
                ),
                stream=stream,
                temperature=temperature,
                text=utils.get_pydantic_model(
                    text, Optional[components.TextExtendedConfig]
                ),
                tool_choice=utils.get_pydantic_model(
                    tool_choice, Optional[components.OpenAIResponsesToolChoiceUnion]
                ),
                tools=utils.get_pydantic_model(
                    tools, Optional[List[components.ResponsesRequestToolUnion]]
                ),
                top_k=top_k,
                top_logprobs=top_logprobs,
                top_p=top_p,
                trace=utils.get_pydantic_model(trace, Optional[components.TraceConfig]),
                truncation=truncation,
                user=user,
            ),
        )

        req = self._build_request(
            method="POST",
            path="/presets/{slug}/responses",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=True,
            request_has_path_params=True,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/json",
            http_headers=http_headers,
            _globals=operations.CreatePresetsResponsesGlobals(
                http_referer=self.sdk_configuration.globals.http_referer,
                x_open_router_title=self.sdk_configuration.globals.x_open_router_title,
                x_open_router_categories=self.sdk_configuration.globals.x_open_router_categories,
            ),
            security=self.sdk_configuration.security,
            get_serialized_body=lambda: utils.serialize_request_body(
                request.responses_request,
                False,
                False,
                "json",
                components.ResponsesRequest,
            ),
            allow_empty_value=None,
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config
            else:
                retries = utils.RetryConfig(
                    "backoff", utils.BackoffStrategy(500, 60000, 1.5, 3600000), True
                )

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["5XX"])

        http_res = self.do_request(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="createPresetsResponses",
                oauth2_scopes=None,
                security_source=get_security_from_env(
                    self.sdk_configuration.security, components.Security
                ),
            ),
            request=req,
            error_status_codes=["400", "401", "403", "404", "409", "4XX", "500", "5XX"],
            retry_config=retry_config,
        )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/json"):
            return unmarshal_json_response(
                components.CreatePresetFromInferenceResponse, http_res
            )
        if utils.match_response(http_res, "400", "application/json"):
            response_data = unmarshal_json_response(
                errors.BadRequestResponseErrorData, http_res
            )
            raise errors.BadRequestResponseError(response_data, http_res)
        if utils.match_response(http_res, "401", "application/json"):
            response_data = unmarshal_json_response(
                errors.UnauthorizedResponseErrorData, http_res
            )
            raise errors.UnauthorizedResponseError(response_data, http_res)
        if utils.match_response(http_res, "403", "application/json"):
            response_data = unmarshal_json_response(
                errors.ForbiddenResponseErrorData, http_res
            )
            raise errors.ForbiddenResponseError(response_data, http_res)
        if utils.match_response(http_res, "404", "application/json"):
            response_data = unmarshal_json_response(
                errors.NotFoundResponseErrorData, http_res
            )
            raise errors.NotFoundResponseError(response_data, http_res)
        if utils.match_response(http_res, "409", "application/json"):
            response_data = unmarshal_json_response(
                errors.ConflictResponseErrorData, http_res
            )
            raise errors.ConflictResponseError(response_data, http_res)
        if utils.match_response(http_res, "500", "application/json"):
            response_data = unmarshal_json_response(
                errors.InternalServerResponseErrorData, http_res
            )
            raise errors.InternalServerResponseError(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.OpenRouterDefaultError(
                "API error occurred", http_res, http_res_text
            )
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.OpenRouterDefaultError(
                "API error occurred", http_res, http_res_text
            )

        raise errors.OpenRouterDefaultError("Unexpected response received", http_res)

    async def create_presets_responses_async(
        self,
        *,
        slug: str,
        http_referer: Optional[str] = None,
        x_open_router_title: Optional[str] = None,
        x_open_router_categories: Optional[str] = None,
        background: OptionalNullable[bool] = UNSET,
        cache_control: Optional[
            Union[
                components.AnthropicCacheControlDirective,
                components.AnthropicCacheControlDirectiveTypedDict,
            ]
        ] = None,
        frequency_penalty: OptionalNullable[float] = UNSET,
        image_config: Optional[
            Union[
                Dict[str, components.ImageConfig],
                Dict[str, components.ImageConfigTypedDict],
            ]
        ] = None,
        include: OptionalNullable[List[components.ResponseIncludesEnum]] = UNSET,
        input: Optional[
            Union[components.InputsUnion, components.InputsUnionTypedDict]
        ] = None,
        instructions: OptionalNullable[str] = UNSET,
        max_output_tokens: OptionalNullable[int] = UNSET,
        max_tool_calls: OptionalNullable[int] = UNSET,
        metadata: OptionalNullable[Dict[str, str]] = UNSET,
        modalities: Optional[List[components.OutputModalityEnum]] = None,
        model: Optional[str] = None,
        models: Optional[List[str]] = None,
        parallel_tool_calls: OptionalNullable[bool] = UNSET,
        plugins: Optional[
            Union[
                List[components.ResponsesRequestPlugin],
                List[components.ResponsesRequestPluginTypedDict],
            ]
        ] = None,
        presence_penalty: OptionalNullable[float] = UNSET,
        previous_response_id: OptionalNullable[str] = UNSET,
        prompt: OptionalNullable[
            Union[
                components.StoredPromptTemplate,
                components.StoredPromptTemplateTypedDict,
            ]
        ] = UNSET,
        prompt_cache_key: OptionalNullable[str] = UNSET,
        provider: OptionalNullable[
            Union[
                components.ProviderPreferences, components.ProviderPreferencesTypedDict
            ]
        ] = UNSET,
        reasoning: OptionalNullable[
            Union[components.ReasoningConfig, components.ReasoningConfigTypedDict]
        ] = UNSET,
        safety_identifier: OptionalNullable[str] = UNSET,
        service_tier: OptionalNullable[components.ResponsesRequestServiceTier] = "auto",
        session_id: Optional[str] = None,
        stop_server_tools_when: Optional[
            Union[
                List[components.StopServerToolsWhenCondition],
                List[components.StopServerToolsWhenConditionTypedDict],
            ]
        ] = None,
        stream: Optional[bool] = False,
        temperature: OptionalNullable[float] = UNSET,
        text: Optional[
            Union[components.TextExtendedConfig, components.TextExtendedConfigTypedDict]
        ] = None,
        tool_choice: Optional[
            Union[
                components.OpenAIResponsesToolChoiceUnion,
                components.OpenAIResponsesToolChoiceUnionTypedDict,
            ]
        ] = None,
        tools: Optional[
            Union[
                List[components.ResponsesRequestToolUnion],
                List[components.ResponsesRequestToolUnionTypedDict],
            ]
        ] = None,
        top_k: Optional[int] = None,
        top_logprobs: OptionalNullable[int] = UNSET,
        top_p: OptionalNullable[float] = UNSET,
        trace: Optional[
            Union[components.TraceConfig, components.TraceConfigTypedDict]
        ] = None,
        truncation: OptionalNullable[components.OpenAIResponsesTruncation] = UNSET,
        user: Optional[str] = None,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> components.CreatePresetFromInferenceResponse:
        r"""Create a preset from a responses request body

        Creates a preset (or a new version of an existing one) from an inference request body. Only fields that overlap with the preset config are persisted; other fields (e.g. `messages`, `stream`, `prompt`) are silently ignored.

        :param slug: URL-safe slug identifying the preset. Created if it does not exist.
        :param http_referer: The app identifier should be your app's URL and is used as the primary identifier for rankings.
            This is used to track API usage per application.

        :param x_open_router_title: The app display name allows you to customize how your app appears in OpenRouter's dashboard.

        :param x_open_router_categories: Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.

        :param background:
        :param cache_control: Enable automatic prompt caching. When set at the top level, the system automatically applies cache breakpoints to the last cacheable block in the request. Currently supported for Anthropic Claude models.
        :param frequency_penalty:
        :param image_config: Provider-specific image configuration options. Keys and values vary by model/provider. See https://openrouter.ai/docs/guides/overview/multimodal/image-generation for more details.
        :param include:
        :param input: Input for a response request - can be a string or array of items
        :param instructions:
        :param max_output_tokens:
        :param max_tool_calls:
        :param metadata: Metadata key-value pairs for the request. Keys must be ≤64 characters and cannot contain brackets. Values must be ≤512 characters. Maximum 16 pairs allowed.
        :param modalities: Output modalities for the response. Supported values are \"text\" and \"image\".
        :param model:
        :param models:
        :param parallel_tool_calls:
        :param plugins: Plugins you want to enable for this request, including their settings.
        :param presence_penalty:
        :param previous_response_id:
        :param prompt:
        :param prompt_cache_key:
        :param provider: When multiple model providers are available, optionally indicate your routing preference.
        :param reasoning: Configuration for reasoning mode in the response
        :param safety_identifier:
        :param service_tier:
        :param session_id: A unique identifier for grouping related requests (e.g., a conversation or agent workflow). When provided, OpenRouter uses it as the sticky routing key, routing all requests in the session to the same provider to maximize prompt cache hits. Also used for observability grouping. If provided in both the request body and the x-session-id header, the body value takes precedence. Maximum of 256 characters.
        :param stop_server_tools_when: Stop conditions for the server-tool agent loop. Any condition firing halts the loop (OR logic). When set, this overrides `max_tool_calls`.
        :param stream:
        :param temperature:
        :param text: Text output configuration including format and verbosity
        :param tool_choice:
        :param tools:
        :param top_k:
        :param top_logprobs:
        :param top_p:
        :param trace: Metadata for observability and tracing. Known keys (trace_id, trace_name, span_name, generation_name, parent_span_id) have special handling. Additional keys are passed through as custom metadata to configured broadcast destinations.
        :param truncation:
        :param user: A unique identifier representing your end-user, which helps distinguish between different users of your app. This allows your app to identify specific users in case of abuse reports, preventing your entire app from being affected by the actions of individual users. Maximum of 256 characters.
        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = operations.CreatePresetsResponsesRequest(
            http_referer=http_referer,
            x_open_router_title=x_open_router_title,
            x_open_router_categories=x_open_router_categories,
            slug=slug,
            responses_request=components.ResponsesRequest(
                background=background,
                cache_control=utils.get_pydantic_model(
                    cache_control, Optional[components.AnthropicCacheControlDirective]
                ),
                frequency_penalty=frequency_penalty,
                image_config=image_config,
                include=include,
                input=utils.get_pydantic_model(input, Optional[components.InputsUnion]),
                instructions=instructions,
                max_output_tokens=max_output_tokens,
                max_tool_calls=max_tool_calls,
                metadata=metadata,
                modalities=modalities,
                model=model,
                models=models,
                parallel_tool_calls=parallel_tool_calls,
                plugins=utils.get_pydantic_model(
                    plugins, Optional[List[components.ResponsesRequestPlugin]]
                ),
                presence_penalty=presence_penalty,
                previous_response_id=previous_response_id,
                prompt=utils.get_pydantic_model(
                    prompt, OptionalNullable[components.StoredPromptTemplate]
                ),
                prompt_cache_key=prompt_cache_key,
                provider=utils.get_pydantic_model(
                    provider, OptionalNullable[components.ProviderPreferences]
                ),
                reasoning=utils.get_pydantic_model(
                    reasoning, OptionalNullable[components.ReasoningConfig]
                ),
                safety_identifier=safety_identifier,
                service_tier=service_tier,
                session_id=session_id,
                stop_server_tools_when=utils.get_pydantic_model(
                    stop_server_tools_when,
                    Optional[List[components.StopServerToolsWhenCondition]],
                ),
                stream=stream,
                temperature=temperature,
                text=utils.get_pydantic_model(
                    text, Optional[components.TextExtendedConfig]
                ),
                tool_choice=utils.get_pydantic_model(
                    tool_choice, Optional[components.OpenAIResponsesToolChoiceUnion]
                ),
                tools=utils.get_pydantic_model(
                    tools, Optional[List[components.ResponsesRequestToolUnion]]
                ),
                top_k=top_k,
                top_logprobs=top_logprobs,
                top_p=top_p,
                trace=utils.get_pydantic_model(trace, Optional[components.TraceConfig]),
                truncation=truncation,
                user=user,
            ),
        )

        req = self._build_request_async(
            method="POST",
            path="/presets/{slug}/responses",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=True,
            request_has_path_params=True,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/json",
            http_headers=http_headers,
            _globals=operations.CreatePresetsResponsesGlobals(
                http_referer=self.sdk_configuration.globals.http_referer,
                x_open_router_title=self.sdk_configuration.globals.x_open_router_title,
                x_open_router_categories=self.sdk_configuration.globals.x_open_router_categories,
            ),
            security=self.sdk_configuration.security,
            get_serialized_body=lambda: utils.serialize_request_body(
                request.responses_request,
                False,
                False,
                "json",
                components.ResponsesRequest,
            ),
            allow_empty_value=None,
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config
            else:
                retries = utils.RetryConfig(
                    "backoff", utils.BackoffStrategy(500, 60000, 1.5, 3600000), True
                )

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["5XX"])

        http_res = await self.do_request_async(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="createPresetsResponses",
                oauth2_scopes=None,
                security_source=get_security_from_env(
                    self.sdk_configuration.security, components.Security
                ),
            ),
            request=req,
            error_status_codes=["400", "401", "403", "404", "409", "4XX", "500", "5XX"],
            retry_config=retry_config,
        )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/json"):
            return unmarshal_json_response(
                components.CreatePresetFromInferenceResponse, http_res
            )
        if utils.match_response(http_res, "400", "application/json"):
            response_data = unmarshal_json_response(
                errors.BadRequestResponseErrorData, http_res
            )
            raise errors.BadRequestResponseError(response_data, http_res)
        if utils.match_response(http_res, "401", "application/json"):
            response_data = unmarshal_json_response(
                errors.UnauthorizedResponseErrorData, http_res
            )
            raise errors.UnauthorizedResponseError(response_data, http_res)
        if utils.match_response(http_res, "403", "application/json"):
            response_data = unmarshal_json_response(
                errors.ForbiddenResponseErrorData, http_res
            )
            raise errors.ForbiddenResponseError(response_data, http_res)
        if utils.match_response(http_res, "404", "application/json"):
            response_data = unmarshal_json_response(
                errors.NotFoundResponseErrorData, http_res
            )
            raise errors.NotFoundResponseError(response_data, http_res)
        if utils.match_response(http_res, "409", "application/json"):
            response_data = unmarshal_json_response(
                errors.ConflictResponseErrorData, http_res
            )
            raise errors.ConflictResponseError(response_data, http_res)
        if utils.match_response(http_res, "500", "application/json"):
            response_data = unmarshal_json_response(
                errors.InternalServerResponseErrorData, http_res
            )
            raise errors.InternalServerResponseError(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.OpenRouterDefaultError(
                "API error occurred", http_res, http_res_text
            )
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.OpenRouterDefaultError(
                "API error occurred", http_res, http_res_text
            )

        raise errors.OpenRouterDefaultError("Unexpected response received", http_res)

    def list_versions(
        self,
        *,
        slug: str,
        http_referer: Optional[str] = None,
        x_open_router_title: Optional[str] = None,
        x_open_router_categories: Optional[str] = None,
        offset: Optional[int] = None,
        limit: Optional[int] = None,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> Optional[operations.ListPresetVersionsResponse]:
        r"""List versions of a preset

        Lists all versions of a preset, ordered by version number ascending (oldest first).

        :param slug: URL-safe slug identifying the preset.
        :param http_referer: The app identifier should be your app's URL and is used as the primary identifier for rankings.
            This is used to track API usage per application.

        :param x_open_router_title: The app display name allows you to customize how your app appears in OpenRouter's dashboard.

        :param x_open_router_categories: Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.

        :param offset: Number of records to skip for pagination
        :param limit: Maximum number of records to return (max 100)
        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = operations.ListPresetVersionsRequest(
            http_referer=http_referer,
            x_open_router_title=x_open_router_title,
            x_open_router_categories=x_open_router_categories,
            slug=slug,
            offset=offset,
            limit=limit,
        )

        req = self._build_request(
            method="GET",
            path="/presets/{slug}/versions",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=False,
            request_has_path_params=True,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/json",
            http_headers=http_headers,
            _globals=operations.ListPresetVersionsGlobals(
                http_referer=self.sdk_configuration.globals.http_referer,
                x_open_router_title=self.sdk_configuration.globals.x_open_router_title,
                x_open_router_categories=self.sdk_configuration.globals.x_open_router_categories,
            ),
            security=self.sdk_configuration.security,
            allow_empty_value=None,
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config
            else:
                retries = utils.RetryConfig(
                    "backoff", utils.BackoffStrategy(500, 60000, 1.5, 3600000), True
                )

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["5XX"])

        http_res = self.do_request(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="listPresetVersions",
                oauth2_scopes=None,
                security_source=get_security_from_env(
                    self.sdk_configuration.security, components.Security
                ),
            ),
            request=req,
            error_status_codes=["400", "401", "404", "4XX", "500", "5XX"],
            retry_config=retry_config,
        )

        def next_func() -> Optional[operations.ListPresetVersionsResponse]:
            body = utils.unmarshal_json(http_res.text, Union[Dict[Any, Any], List[Any]])

            offset = request.offset if not request.offset is None else 0

            if not http_res.text:
                return None
            results = JSONPath("$.data").parse(body)
            if len(results) == 0 or len(results[0]) == 0:
                return None
            limit = request.limit if not request.limit is None else 0
            if len(results[0]) < limit:
                return None
            next_offset = offset + len(results[0])

            return self.list_versions(
                slug=slug,
                http_referer=http_referer,
                x_open_router_title=x_open_router_title,
                x_open_router_categories=x_open_router_categories,
                offset=next_offset,
                limit=limit,
                retries=retries,
            )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/json"):
            return operations.ListPresetVersionsResponse(
                result=unmarshal_json_response(
                    components.ListPresetVersionsResponse, http_res
                ),
                next=next_func,
            )
        if utils.match_response(http_res, "400", "application/json"):
            response_data = unmarshal_json_response(
                errors.BadRequestResponseErrorData, http_res
            )
            raise errors.BadRequestResponseError(response_data, http_res)
        if utils.match_response(http_res, "401", "application/json"):
            response_data = unmarshal_json_response(
                errors.UnauthorizedResponseErrorData, http_res
            )
            raise errors.UnauthorizedResponseError(response_data, http_res)
        if utils.match_response(http_res, "404", "application/json"):
            response_data = unmarshal_json_response(
                errors.NotFoundResponseErrorData, http_res
            )
            raise errors.NotFoundResponseError(response_data, http_res)
        if utils.match_response(http_res, "500", "application/json"):
            response_data = unmarshal_json_response(
                errors.InternalServerResponseErrorData, http_res
            )
            raise errors.InternalServerResponseError(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.OpenRouterDefaultError(
                "API error occurred", http_res, http_res_text
            )
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.OpenRouterDefaultError(
                "API error occurred", http_res, http_res_text
            )

        raise errors.OpenRouterDefaultError("Unexpected response received", http_res)

    async def list_versions_async(
        self,
        *,
        slug: str,
        http_referer: Optional[str] = None,
        x_open_router_title: Optional[str] = None,
        x_open_router_categories: Optional[str] = None,
        offset: Optional[int] = None,
        limit: Optional[int] = None,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> Optional[operations.ListPresetVersionsResponse]:
        r"""List versions of a preset

        Lists all versions of a preset, ordered by version number ascending (oldest first).

        :param slug: URL-safe slug identifying the preset.
        :param http_referer: The app identifier should be your app's URL and is used as the primary identifier for rankings.
            This is used to track API usage per application.

        :param x_open_router_title: The app display name allows you to customize how your app appears in OpenRouter's dashboard.

        :param x_open_router_categories: Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.

        :param offset: Number of records to skip for pagination
        :param limit: Maximum number of records to return (max 100)
        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = operations.ListPresetVersionsRequest(
            http_referer=http_referer,
            x_open_router_title=x_open_router_title,
            x_open_router_categories=x_open_router_categories,
            slug=slug,
            offset=offset,
            limit=limit,
        )

        req = self._build_request_async(
            method="GET",
            path="/presets/{slug}/versions",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=False,
            request_has_path_params=True,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/json",
            http_headers=http_headers,
            _globals=operations.ListPresetVersionsGlobals(
                http_referer=self.sdk_configuration.globals.http_referer,
                x_open_router_title=self.sdk_configuration.globals.x_open_router_title,
                x_open_router_categories=self.sdk_configuration.globals.x_open_router_categories,
            ),
            security=self.sdk_configuration.security,
            allow_empty_value=None,
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config
            else:
                retries = utils.RetryConfig(
                    "backoff", utils.BackoffStrategy(500, 60000, 1.5, 3600000), True
                )

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["5XX"])

        http_res = await self.do_request_async(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="listPresetVersions",
                oauth2_scopes=None,
                security_source=get_security_from_env(
                    self.sdk_configuration.security, components.Security
                ),
            ),
            request=req,
            error_status_codes=["400", "401", "404", "4XX", "500", "5XX"],
            retry_config=retry_config,
        )

        def next_func() -> Awaitable[Optional[operations.ListPresetVersionsResponse]]:
            body = utils.unmarshal_json(http_res.text, Union[Dict[Any, Any], List[Any]])

            async def empty_result():
                return None

            offset = request.offset if not request.offset is None else 0

            if not http_res.text:
                return empty_result()
            results = JSONPath("$.data").parse(body)
            if len(results) == 0 or len(results[0]) == 0:
                return empty_result()
            limit = request.limit if not request.limit is None else 0
            if len(results[0]) < limit:
                return empty_result()
            next_offset = offset + len(results[0])

            return self.list_versions_async(
                slug=slug,
                http_referer=http_referer,
                x_open_router_title=x_open_router_title,
                x_open_router_categories=x_open_router_categories,
                offset=next_offset,
                limit=limit,
                retries=retries,
            )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/json"):
            return operations.ListPresetVersionsResponse(
                result=unmarshal_json_response(
                    components.ListPresetVersionsResponse, http_res
                ),
                next=next_func,
            )
        if utils.match_response(http_res, "400", "application/json"):
            response_data = unmarshal_json_response(
                errors.BadRequestResponseErrorData, http_res
            )
            raise errors.BadRequestResponseError(response_data, http_res)
        if utils.match_response(http_res, "401", "application/json"):
            response_data = unmarshal_json_response(
                errors.UnauthorizedResponseErrorData, http_res
            )
            raise errors.UnauthorizedResponseError(response_data, http_res)
        if utils.match_response(http_res, "404", "application/json"):
            response_data = unmarshal_json_response(
                errors.NotFoundResponseErrorData, http_res
            )
            raise errors.NotFoundResponseError(response_data, http_res)
        if utils.match_response(http_res, "500", "application/json"):
            response_data = unmarshal_json_response(
                errors.InternalServerResponseErrorData, http_res
            )
            raise errors.InternalServerResponseError(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.OpenRouterDefaultError(
                "API error occurred", http_res, http_res_text
            )
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.OpenRouterDefaultError(
                "API error occurred", http_res, http_res_text
            )

        raise errors.OpenRouterDefaultError("Unexpected response received", http_res)

    def get_version(
        self,
        *,
        slug: str,
        version: str,
        http_referer: Optional[str] = None,
        x_open_router_title: Optional[str] = None,
        x_open_router_categories: Optional[str] = None,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> components.GetPresetVersionResponse:
        r"""Get a specific version of a preset

        Retrieves a specific version of a preset by its slug and version number.

        :param slug: URL-safe slug identifying the preset.
        :param version: Version number of the preset.
        :param http_referer: The app identifier should be your app's URL and is used as the primary identifier for rankings.
            This is used to track API usage per application.

        :param x_open_router_title: The app display name allows you to customize how your app appears in OpenRouter's dashboard.

        :param x_open_router_categories: Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.

        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = operations.GetPresetVersionRequest(
            http_referer=http_referer,
            x_open_router_title=x_open_router_title,
            x_open_router_categories=x_open_router_categories,
            slug=slug,
            version=version,
        )

        req = self._build_request(
            method="GET",
            path="/presets/{slug}/versions/{version}",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=False,
            request_has_path_params=True,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/json",
            http_headers=http_headers,
            _globals=operations.GetPresetVersionGlobals(
                http_referer=self.sdk_configuration.globals.http_referer,
                x_open_router_title=self.sdk_configuration.globals.x_open_router_title,
                x_open_router_categories=self.sdk_configuration.globals.x_open_router_categories,
            ),
            security=self.sdk_configuration.security,
            allow_empty_value=None,
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config
            else:
                retries = utils.RetryConfig(
                    "backoff", utils.BackoffStrategy(500, 60000, 1.5, 3600000), True
                )

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["5XX"])

        http_res = self.do_request(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="getPresetVersion",
                oauth2_scopes=None,
                security_source=get_security_from_env(
                    self.sdk_configuration.security, components.Security
                ),
            ),
            request=req,
            error_status_codes=["400", "401", "404", "4XX", "500", "5XX"],
            retry_config=retry_config,
        )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/json"):
            return unmarshal_json_response(
                components.GetPresetVersionResponse, http_res
            )
        if utils.match_response(http_res, "400", "application/json"):
            response_data = unmarshal_json_response(
                errors.BadRequestResponseErrorData, http_res
            )
            raise errors.BadRequestResponseError(response_data, http_res)
        if utils.match_response(http_res, "401", "application/json"):
            response_data = unmarshal_json_response(
                errors.UnauthorizedResponseErrorData, http_res
            )
            raise errors.UnauthorizedResponseError(response_data, http_res)
        if utils.match_response(http_res, "404", "application/json"):
            response_data = unmarshal_json_response(
                errors.NotFoundResponseErrorData, http_res
            )
            raise errors.NotFoundResponseError(response_data, http_res)
        if utils.match_response(http_res, "500", "application/json"):
            response_data = unmarshal_json_response(
                errors.InternalServerResponseErrorData, http_res
            )
            raise errors.InternalServerResponseError(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.OpenRouterDefaultError(
                "API error occurred", http_res, http_res_text
            )
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.OpenRouterDefaultError(
                "API error occurred", http_res, http_res_text
            )

        raise errors.OpenRouterDefaultError("Unexpected response received", http_res)

    async def get_version_async(
        self,
        *,
        slug: str,
        version: str,
        http_referer: Optional[str] = None,
        x_open_router_title: Optional[str] = None,
        x_open_router_categories: Optional[str] = None,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> components.GetPresetVersionResponse:
        r"""Get a specific version of a preset

        Retrieves a specific version of a preset by its slug and version number.

        :param slug: URL-safe slug identifying the preset.
        :param version: Version number of the preset.
        :param http_referer: The app identifier should be your app's URL and is used as the primary identifier for rankings.
            This is used to track API usage per application.

        :param x_open_router_title: The app display name allows you to customize how your app appears in OpenRouter's dashboard.

        :param x_open_router_categories: Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings.

        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = operations.GetPresetVersionRequest(
            http_referer=http_referer,
            x_open_router_title=x_open_router_title,
            x_open_router_categories=x_open_router_categories,
            slug=slug,
            version=version,
        )

        req = self._build_request_async(
            method="GET",
            path="/presets/{slug}/versions/{version}",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=False,
            request_has_path_params=True,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/json",
            http_headers=http_headers,
            _globals=operations.GetPresetVersionGlobals(
                http_referer=self.sdk_configuration.globals.http_referer,
                x_open_router_title=self.sdk_configuration.globals.x_open_router_title,
                x_open_router_categories=self.sdk_configuration.globals.x_open_router_categories,
            ),
            security=self.sdk_configuration.security,
            allow_empty_value=None,
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config
            else:
                retries = utils.RetryConfig(
                    "backoff", utils.BackoffStrategy(500, 60000, 1.5, 3600000), True
                )

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["5XX"])

        http_res = await self.do_request_async(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="getPresetVersion",
                oauth2_scopes=None,
                security_source=get_security_from_env(
                    self.sdk_configuration.security, components.Security
                ),
            ),
            request=req,
            error_status_codes=["400", "401", "404", "4XX", "500", "5XX"],
            retry_config=retry_config,
        )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/json"):
            return unmarshal_json_response(
                components.GetPresetVersionResponse, http_res
            )
        if utils.match_response(http_res, "400", "application/json"):
            response_data = unmarshal_json_response(
                errors.BadRequestResponseErrorData, http_res
            )
            raise errors.BadRequestResponseError(response_data, http_res)
        if utils.match_response(http_res, "401", "application/json"):
            response_data = unmarshal_json_response(
                errors.UnauthorizedResponseErrorData, http_res
            )
            raise errors.UnauthorizedResponseError(response_data, http_res)
        if utils.match_response(http_res, "404", "application/json"):
            response_data = unmarshal_json_response(
                errors.NotFoundResponseErrorData, http_res
            )
            raise errors.NotFoundResponseError(response_data, http_res)
        if utils.match_response(http_res, "500", "application/json"):
            response_data = unmarshal_json_response(
                errors.InternalServerResponseErrorData, http_res
            )
            raise errors.InternalServerResponseError(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.OpenRouterDefaultError(
                "API error occurred", http_res, http_res_text
            )
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.OpenRouterDefaultError(
                "API error occurred", http_res, http_res_text
            )

        raise errors.OpenRouterDefaultError("Unexpected response received", http_res)
