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

from __future__ import annotations
from .anthropicallowedcallers import AnthropicAllowedCallers
from .anthropiccachecontroldirective import (
    AnthropicCacheControlDirective,
    AnthropicCacheControlDirectiveTypedDict,
)
from .anthropiccachecontrolttl import AnthropicCacheControlTTL
from .anthropicinputtokensclearatleast import (
    AnthropicInputTokensClearAtLeast,
    AnthropicInputTokensClearAtLeastTypedDict,
)
from .anthropicinputtokenstrigger import (
    AnthropicInputTokensTrigger,
    AnthropicInputTokensTriggerTypedDict,
)
from .anthropictextblockparam import (
    AnthropicTextBlockParam,
    AnthropicTextBlockParamTypedDict,
)
from .anthropicthinkingdisplay import AnthropicThinkingDisplay
from .anthropicthinkingturns import (
    AnthropicThinkingTurns,
    AnthropicThinkingTurnsTypedDict,
)
from .anthropictooluseskeep import AnthropicToolUsesKeep, AnthropicToolUsesKeepTypedDict
from .anthropictoolusestrigger import (
    AnthropicToolUsesTrigger,
    AnthropicToolUsesTriggerTypedDict,
)
from .anthropicwebsearchtooluserlocation import (
    AnthropicWebSearchToolUserLocation,
    AnthropicWebSearchToolUserLocationTypedDict,
)
from .autorouterplugin import AutoRouterPlugin, AutoRouterPluginTypedDict
from .bashservertool import BashServerTool, BashServerToolTypedDict
from .chatsearchmodelsservertool import (
    ChatSearchModelsServerTool,
    ChatSearchModelsServerToolTypedDict,
)
from .contextcompressionplugin import (
    ContextCompressionPlugin,
    ContextCompressionPluginTypedDict,
)
from .datetimeservertool import DatetimeServerTool, DatetimeServerToolTypedDict
from .fileparserplugin import FileParserPlugin, FileParserPluginTypedDict
from .fusionplugin import FusionPlugin, FusionPluginTypedDict
from .imagegenerationservertool_openrouter import (
    ImageGenerationServerToolOpenRouter,
    ImageGenerationServerToolOpenRouterTypedDict,
)
from .messagesfallbackparam import MessagesFallbackParam, MessagesFallbackParamTypedDict
from .messagesmessageparam import MessagesMessageParam, MessagesMessageParamTypedDict
from .messagesoutputconfig import MessagesOutputConfig, MessagesOutputConfigTypedDict
from .moderationplugin import ModerationPlugin, ModerationPluginTypedDict
from .openrouterwebsearchservertool import (
    OpenRouterWebSearchServerTool,
    OpenRouterWebSearchServerToolTypedDict,
)
from .paretorouterplugin import ParetoRouterPlugin, ParetoRouterPluginTypedDict
from .providerpreferences import ProviderPreferences, ProviderPreferencesTypedDict
from .responsehealingplugin import ResponseHealingPlugin, ResponseHealingPluginTypedDict
from .stopservertoolswhencondition import (
    StopServerToolsWhenCondition,
    StopServerToolsWhenConditionTypedDict,
)
from .traceconfig import TraceConfig, TraceConfigTypedDict
from .webfetchplugin import WebFetchPlugin, WebFetchPluginTypedDict
from .webfetchservertool import WebFetchServerTool, WebFetchServerToolTypedDict
from .websearchplugin import WebSearchPlugin, WebSearchPluginTypedDict
from openrouter.types import (
    BaseModel,
    Nullable,
    OptionalNullable,
    UNSET,
    UNSET_SENTINEL,
    UnrecognizedStr,
)
from openrouter.utils import get_discriminator, validate_open_enum
import pydantic
from pydantic import ConfigDict, Discriminator, Tag, model_serializer
from pydantic.functional_validators import PlainValidator
from typing import Any, Dict, List, Literal, Optional, Union
from typing_extensions import Annotated, NotRequired, TypeAliasType, TypedDict


EditTypeInputTokens = Literal["input_tokens",]


class TriggerInputTokensTypedDict(TypedDict):
    type: EditTypeInputTokens
    value: int


class TriggerInputTokens(BaseModel):
    type: EditTypeInputTokens

    value: int


TypeCompact20260112 = Literal["compact_20260112",]


class EditCompact20260112TypedDict(TypedDict):
    type: TypeCompact20260112
    instructions: NotRequired[Nullable[str]]
    pause_after_compaction: NotRequired[bool]
    trigger: NotRequired[Nullable[TriggerInputTokensTypedDict]]


class EditCompact20260112(BaseModel):
    type: TypeCompact20260112

    instructions: OptionalNullable[str] = UNSET

    pause_after_compaction: Optional[bool] = None

    trigger: OptionalNullable[TriggerInputTokens] = UNSET

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = ["instructions", "pause_after_compaction", "trigger"]
        nullable_fields = ["instructions", "trigger"]
        null_default_fields = []

        serialized = handler(self)

        m = {}

        for n, f in type(self).model_fields.items():
            k = f.alias or n
            val = serialized.get(k)
            serialized.pop(k, None)

            optional_nullable = k in optional_fields and k in nullable_fields
            is_set = (
                self.__pydantic_fields_set__.intersection({n})
                or k in null_default_fields
            )  # pylint: disable=no-member

            if val is not None and val != UNSET_SENTINEL:
                m[k] = val
            elif val != UNSET_SENTINEL and (
                not k in optional_fields or (optional_nullable and is_set)
            ):
                m[k] = val

        return m


KeepEnum = Literal["all",]


KeepType = Literal["all",]


class KeepAllTypedDict(TypedDict):
    type: KeepType


class KeepAll(BaseModel):
    type: KeepType


KeepTypedDict = TypeAliasType(
    "KeepTypedDict", Union[KeepAllTypedDict, AnthropicThinkingTurnsTypedDict, KeepEnum]
)


Keep = TypeAliasType("Keep", Union[KeepAll, AnthropicThinkingTurns, KeepEnum])


TypeClearThinking20251015 = Literal["clear_thinking_20251015",]


class EditClearThinking20251015TypedDict(TypedDict):
    type: TypeClearThinking20251015
    keep: NotRequired[KeepTypedDict]


class EditClearThinking20251015(BaseModel):
    type: TypeClearThinking20251015

    keep: Optional[Keep] = None


ClearToolInputsTypedDict = TypeAliasType(
    "ClearToolInputsTypedDict", Union[bool, List[str], Any]
)


ClearToolInputs = TypeAliasType("ClearToolInputs", Union[bool, List[str], Any])


TriggerTypedDict = TypeAliasType(
    "TriggerTypedDict",
    Union[AnthropicInputTokensTriggerTypedDict, AnthropicToolUsesTriggerTypedDict],
)


Trigger = Annotated[
    Union[
        Annotated[AnthropicInputTokensTrigger, Tag("input_tokens")],
        Annotated[AnthropicToolUsesTrigger, Tag("tool_uses")],
    ],
    Discriminator(lambda m: get_discriminator(m, "type", "type")),
]


TypeClearToolUses20250919 = Literal["clear_tool_uses_20250919",]


class EditClearToolUses20250919TypedDict(TypedDict):
    type: TypeClearToolUses20250919
    clear_at_least: NotRequired[Nullable[AnthropicInputTokensClearAtLeastTypedDict]]
    clear_tool_inputs: NotRequired[Nullable[ClearToolInputsTypedDict]]
    exclude_tools: NotRequired[Nullable[List[str]]]
    keep: NotRequired[AnthropicToolUsesKeepTypedDict]
    trigger: NotRequired[TriggerTypedDict]


class EditClearToolUses20250919(BaseModel):
    type: TypeClearToolUses20250919

    clear_at_least: OptionalNullable[AnthropicInputTokensClearAtLeast] = UNSET

    clear_tool_inputs: OptionalNullable[ClearToolInputs] = UNSET

    exclude_tools: OptionalNullable[List[str]] = UNSET

    keep: Optional[AnthropicToolUsesKeep] = None

    trigger: Optional[Trigger] = None

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = [
            "clear_at_least",
            "clear_tool_inputs",
            "exclude_tools",
            "keep",
            "trigger",
        ]
        nullable_fields = ["clear_at_least", "clear_tool_inputs", "exclude_tools"]
        null_default_fields = []

        serialized = handler(self)

        m = {}

        for n, f in type(self).model_fields.items():
            k = f.alias or n
            val = serialized.get(k)
            serialized.pop(k, None)

            optional_nullable = k in optional_fields and k in nullable_fields
            is_set = (
                self.__pydantic_fields_set__.intersection({n})
                or k in null_default_fields
            )  # pylint: disable=no-member

            if val is not None and val != UNSET_SENTINEL:
                m[k] = val
            elif val != UNSET_SENTINEL and (
                not k in optional_fields or (optional_nullable and is_set)
            ):
                m[k] = val

        return m


EditTypedDict = TypeAliasType(
    "EditTypedDict",
    Union[
        EditClearThinking20251015TypedDict,
        EditCompact20260112TypedDict,
        EditClearToolUses20250919TypedDict,
    ],
)


Edit = Annotated[
    Union[
        Annotated[EditClearToolUses20250919, Tag("clear_tool_uses_20250919")],
        Annotated[EditClearThinking20251015, Tag("clear_thinking_20251015")],
        Annotated[EditCompact20260112, Tag("compact_20260112")],
    ],
    Discriminator(lambda m: get_discriminator(m, "type", "type")),
]


class ContextManagementTypedDict(TypedDict):
    edits: NotRequired[List[EditTypedDict]]


class ContextManagement(BaseModel):
    edits: Optional[List[Edit]] = None


class MetadataTypedDict(TypedDict):
    user_id: NotRequired[Nullable[str]]


class Metadata(BaseModel):
    user_id: OptionalNullable[str] = UNSET

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = ["user_id"]
        nullable_fields = ["user_id"]
        null_default_fields = []

        serialized = handler(self)

        m = {}

        for n, f in type(self).model_fields.items():
            k = f.alias or n
            val = serialized.get(k)
            serialized.pop(k, None)

            optional_nullable = k in optional_fields and k in nullable_fields
            is_set = (
                self.__pydantic_fields_set__.intersection({n})
                or k in null_default_fields
            )  # pylint: disable=no-member

            if val is not None and val != UNSET_SENTINEL:
                m[k] = val
            elif val != UNSET_SENTINEL and (
                not k in optional_fields or (optional_nullable and is_set)
            ):
                m[k] = val

        return m


MessagesRequestPluginTypedDict = TypeAliasType(
    "MessagesRequestPluginTypedDict",
    Union[
        ModerationPluginTypedDict,
        ResponseHealingPluginTypedDict,
        FileParserPluginTypedDict,
        ContextCompressionPluginTypedDict,
        ParetoRouterPluginTypedDict,
        AutoRouterPluginTypedDict,
        WebFetchPluginTypedDict,
        FusionPluginTypedDict,
        WebSearchPluginTypedDict,
    ],
)


MessagesRequestPlugin = Annotated[
    Union[
        Annotated[AutoRouterPlugin, Tag("auto-router")],
        Annotated[ContextCompressionPlugin, Tag("context-compression")],
        Annotated[FileParserPlugin, Tag("file-parser")],
        Annotated[FusionPlugin, Tag("fusion")],
        Annotated[ModerationPlugin, Tag("moderation")],
        Annotated[ParetoRouterPlugin, Tag("pareto-router")],
        Annotated[ResponseHealingPlugin, Tag("response-healing")],
        Annotated[WebSearchPlugin, Tag("web")],
        Annotated[WebFetchPlugin, Tag("web-fetch")],
    ],
    Discriminator(lambda m: get_discriminator(m, "id", "id")),
]


Speed = Union[
    Literal[
        "fast",
        "standard",
    ],
    UnrecognizedStr,
]
r"""Controls output generation speed. When set to `fast`, uses a higher-speed inference configuration at premium pricing. Defaults to `standard` when omitted."""


SystemTypedDict = TypeAliasType(
    "SystemTypedDict", Union[str, List[AnthropicTextBlockParamTypedDict]]
)


System = TypeAliasType("System", Union[str, List[AnthropicTextBlockParam]])


TypeAdaptive = Literal["adaptive",]


class ThinkingAdaptiveTypedDict(TypedDict):
    type: TypeAdaptive
    display: NotRequired[Nullable[AnthropicThinkingDisplay]]


class ThinkingAdaptive(BaseModel):
    type: TypeAdaptive

    display: Annotated[
        OptionalNullable[AnthropicThinkingDisplay],
        PlainValidator(validate_open_enum(False)),
    ] = UNSET

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = ["display"]
        nullable_fields = ["display"]
        null_default_fields = []

        serialized = handler(self)

        m = {}

        for n, f in type(self).model_fields.items():
            k = f.alias or n
            val = serialized.get(k)
            serialized.pop(k, None)

            optional_nullable = k in optional_fields and k in nullable_fields
            is_set = (
                self.__pydantic_fields_set__.intersection({n})
                or k in null_default_fields
            )  # pylint: disable=no-member

            if val is not None and val != UNSET_SENTINEL:
                m[k] = val
            elif val != UNSET_SENTINEL and (
                not k in optional_fields or (optional_nullable and is_set)
            ):
                m[k] = val

        return m


TypeDisabled = Literal["disabled",]


class ThinkingDisabledTypedDict(TypedDict):
    type: TypeDisabled


class ThinkingDisabled(BaseModel):
    type: TypeDisabled


TypeEnabled = Literal["enabled",]


class ThinkingEnabledTypedDict(TypedDict):
    budget_tokens: int
    type: TypeEnabled
    display: NotRequired[Nullable[AnthropicThinkingDisplay]]


class ThinkingEnabled(BaseModel):
    budget_tokens: int

    type: TypeEnabled

    display: Annotated[
        OptionalNullable[AnthropicThinkingDisplay],
        PlainValidator(validate_open_enum(False)),
    ] = UNSET

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = ["display"]
        nullable_fields = ["display"]
        null_default_fields = []

        serialized = handler(self)

        m = {}

        for n, f in type(self).model_fields.items():
            k = f.alias or n
            val = serialized.get(k)
            serialized.pop(k, None)

            optional_nullable = k in optional_fields and k in nullable_fields
            is_set = (
                self.__pydantic_fields_set__.intersection({n})
                or k in null_default_fields
            )  # pylint: disable=no-member

            if val is not None and val != UNSET_SENTINEL:
                m[k] = val
            elif val != UNSET_SENTINEL and (
                not k in optional_fields or (optional_nullable and is_set)
            ):
                m[k] = val

        return m


ThinkingTypedDict = TypeAliasType(
    "ThinkingTypedDict",
    Union[
        ThinkingDisabledTypedDict, ThinkingAdaptiveTypedDict, ThinkingEnabledTypedDict
    ],
)


Thinking = Annotated[
    Union[
        Annotated[ThinkingEnabled, Tag("enabled")],
        Annotated[ThinkingDisabled, Tag("disabled")],
        Annotated[ThinkingAdaptive, Tag("adaptive")],
    ],
    Discriminator(lambda m: get_discriminator(m, "type", "type")),
]


TypeTool = Literal["tool",]


class ToolChoiceToolTypedDict(TypedDict):
    name: str
    type: TypeTool
    disable_parallel_tool_use: NotRequired[bool]


class ToolChoiceTool(BaseModel):
    name: str

    type: TypeTool

    disable_parallel_tool_use: Optional[bool] = None


TypeNone = Literal["none",]


class ToolChoiceNoneTypedDict(TypedDict):
    type: TypeNone


class ToolChoiceNone(BaseModel):
    type: TypeNone


TypeAny = Literal["any",]


class ToolChoiceAnyTypedDict(TypedDict):
    type: TypeAny
    disable_parallel_tool_use: NotRequired[bool]


class ToolChoiceAny(BaseModel):
    type: TypeAny

    disable_parallel_tool_use: Optional[bool] = None


ToolChoiceTypeAuto = Literal["auto",]


class ToolChoiceAutoTypedDict(TypedDict):
    type: ToolChoiceTypeAuto
    disable_parallel_tool_use: NotRequired[bool]


class ToolChoiceAuto(BaseModel):
    type: ToolChoiceTypeAuto

    disable_parallel_tool_use: Optional[bool] = None


ToolChoiceTypedDict = TypeAliasType(
    "ToolChoiceTypedDict",
    Union[
        ToolChoiceNoneTypedDict,
        ToolChoiceAutoTypedDict,
        ToolChoiceAnyTypedDict,
        ToolChoiceToolTypedDict,
    ],
)


ToolChoice = Annotated[
    Union[
        Annotated[ToolChoiceAuto, Tag("auto")],
        Annotated[ToolChoiceAny, Tag("any")],
        Annotated[ToolChoiceNone, Tag("none")],
        Annotated[ToolChoiceTool, Tag("tool")],
    ],
    Discriminator(lambda m: get_discriminator(m, "type", "type")),
]


class MessagesRequestToolTypedDict(TypedDict):
    type: str


class MessagesRequestTool(BaseModel):
    model_config = ConfigDict(
        populate_by_name=True, arbitrary_types_allowed=True, extra="allow"
    )
    __pydantic_extra__: Dict[str, Nullable[Any]] = pydantic.Field(init=False)

    type: str

    @property
    def additional_properties(self):
        return self.__pydantic_extra__

    @additional_properties.setter
    def additional_properties(self, value):
        self.__pydantic_extra__ = value  # pyright: ignore[reportIncompatibleVariableOverride]


ToolTypeEphemeral = Literal["ephemeral",]


class CachingTypedDict(TypedDict):
    r"""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."""

    type: ToolTypeEphemeral
    ttl: NotRequired[AnthropicCacheControlTTL]


class Caching(BaseModel):
    r"""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."""

    type: ToolTypeEphemeral

    ttl: Annotated[
        Optional[AnthropicCacheControlTTL], PlainValidator(validate_open_enum(False))
    ] = None


NameAdvisor = Literal["advisor",]


TypeAdvisor20260301 = Literal["advisor_20260301",]


class ToolAdvisor20260301TypedDict(TypedDict):
    model: str
    name: NameAdvisor
    type: TypeAdvisor20260301
    allowed_callers: NotRequired[List[AnthropicAllowedCallers]]
    cache_control: NotRequired[AnthropicCacheControlDirectiveTypedDict]
    r"""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."""
    caching: NotRequired[Nullable[CachingTypedDict]]
    defer_loading: NotRequired[bool]
    max_uses: NotRequired[int]


class ToolAdvisor20260301(BaseModel):
    model: str

    name: NameAdvisor

    type: TypeAdvisor20260301

    allowed_callers: Optional[
        List[
            Annotated[
                AnthropicAllowedCallers, PlainValidator(validate_open_enum(False))
            ]
        ]
    ] = None

    cache_control: Optional[AnthropicCacheControlDirective] = None
    r"""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."""

    caching: OptionalNullable[Caching] = UNSET

    defer_loading: Optional[bool] = None

    max_uses: Optional[int] = None

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = [
            "allowed_callers",
            "cache_control",
            "caching",
            "defer_loading",
            "max_uses",
        ]
        nullable_fields = ["caching"]
        null_default_fields = []

        serialized = handler(self)

        m = {}

        for n, f in type(self).model_fields.items():
            k = f.alias or n
            val = serialized.get(k)
            serialized.pop(k, None)

            optional_nullable = k in optional_fields and k in nullable_fields
            is_set = (
                self.__pydantic_fields_set__.intersection({n})
                or k in null_default_fields
            )  # pylint: disable=no-member

            if val is not None and val != UNSET_SENTINEL:
                m[k] = val
            elif val != UNSET_SENTINEL and (
                not k in optional_fields or (optional_nullable and is_set)
            ):
                m[k] = val

        return m


NameWebSearch2 = Literal["web_search",]


TypeWebSearch20260209 = Literal["web_search_20260209",]


class ToolWebSearch20260209TypedDict(TypedDict):
    name: NameWebSearch2
    type: TypeWebSearch20260209
    allowed_callers: NotRequired[List[AnthropicAllowedCallers]]
    allowed_domains: NotRequired[Nullable[List[str]]]
    blocked_domains: NotRequired[Nullable[List[str]]]
    cache_control: NotRequired[AnthropicCacheControlDirectiveTypedDict]
    r"""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."""
    max_uses: NotRequired[Nullable[int]]
    user_location: NotRequired[Nullable[AnthropicWebSearchToolUserLocationTypedDict]]


class ToolWebSearch20260209(BaseModel):
    name: NameWebSearch2

    type: TypeWebSearch20260209

    allowed_callers: Optional[
        List[
            Annotated[
                AnthropicAllowedCallers, PlainValidator(validate_open_enum(False))
            ]
        ]
    ] = None

    allowed_domains: OptionalNullable[List[str]] = UNSET

    blocked_domains: OptionalNullable[List[str]] = UNSET

    cache_control: Optional[AnthropicCacheControlDirective] = None
    r"""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."""

    max_uses: OptionalNullable[int] = UNSET

    user_location: OptionalNullable[AnthropicWebSearchToolUserLocation] = UNSET

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = [
            "allowed_callers",
            "allowed_domains",
            "blocked_domains",
            "cache_control",
            "max_uses",
            "user_location",
        ]
        nullable_fields = [
            "allowed_domains",
            "blocked_domains",
            "max_uses",
            "user_location",
        ]
        null_default_fields = []

        serialized = handler(self)

        m = {}

        for n, f in type(self).model_fields.items():
            k = f.alias or n
            val = serialized.get(k)
            serialized.pop(k, None)

            optional_nullable = k in optional_fields and k in nullable_fields
            is_set = (
                self.__pydantic_fields_set__.intersection({n})
                or k in null_default_fields
            )  # pylint: disable=no-member

            if val is not None and val != UNSET_SENTINEL:
                m[k] = val
            elif val != UNSET_SENTINEL and (
                not k in optional_fields or (optional_nullable and is_set)
            ):
                m[k] = val

        return m


NameWebSearch1 = Literal["web_search",]


TypeWebSearch20250305 = Literal["web_search_20250305",]


class ToolWebSearch20250305TypedDict(TypedDict):
    name: NameWebSearch1
    type: TypeWebSearch20250305
    allowed_domains: NotRequired[Nullable[List[str]]]
    blocked_domains: NotRequired[Nullable[List[str]]]
    cache_control: NotRequired[AnthropicCacheControlDirectiveTypedDict]
    r"""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."""
    max_uses: NotRequired[Nullable[int]]
    user_location: NotRequired[Nullable[AnthropicWebSearchToolUserLocationTypedDict]]


class ToolWebSearch20250305(BaseModel):
    name: NameWebSearch1

    type: TypeWebSearch20250305

    allowed_domains: OptionalNullable[List[str]] = UNSET

    blocked_domains: OptionalNullable[List[str]] = UNSET

    cache_control: Optional[AnthropicCacheControlDirective] = None
    r"""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."""

    max_uses: OptionalNullable[int] = UNSET

    user_location: OptionalNullable[AnthropicWebSearchToolUserLocation] = UNSET

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = [
            "allowed_domains",
            "blocked_domains",
            "cache_control",
            "max_uses",
            "user_location",
        ]
        nullable_fields = [
            "allowed_domains",
            "blocked_domains",
            "max_uses",
            "user_location",
        ]
        null_default_fields = []

        serialized = handler(self)

        m = {}

        for n, f in type(self).model_fields.items():
            k = f.alias or n
            val = serialized.get(k)
            serialized.pop(k, None)

            optional_nullable = k in optional_fields and k in nullable_fields
            is_set = (
                self.__pydantic_fields_set__.intersection({n})
                or k in null_default_fields
            )  # pylint: disable=no-member

            if val is not None and val != UNSET_SENTINEL:
                m[k] = val
            elif val != UNSET_SENTINEL and (
                not k in optional_fields or (optional_nullable and is_set)
            ):
                m[k] = val

        return m


NameStrReplaceEditor = Literal["str_replace_editor",]


TypeTextEditor20250124 = Literal["text_editor_20250124",]


class ToolTextEditor20250124TypedDict(TypedDict):
    name: NameStrReplaceEditor
    type: TypeTextEditor20250124
    cache_control: NotRequired[AnthropicCacheControlDirectiveTypedDict]
    r"""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."""


class ToolTextEditor20250124(BaseModel):
    name: NameStrReplaceEditor

    type: TypeTextEditor20250124

    cache_control: Optional[AnthropicCacheControlDirective] = None
    r"""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."""


NameBash = Literal["bash",]


TypeBash20250124 = Literal["bash_20250124",]


class ToolBash20250124TypedDict(TypedDict):
    name: NameBash
    type: TypeBash20250124
    cache_control: NotRequired[AnthropicCacheControlDirectiveTypedDict]
    r"""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."""


class ToolBash20250124(BaseModel):
    name: NameBash

    type: TypeBash20250124

    cache_control: Optional[AnthropicCacheControlDirective] = None
    r"""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."""


class InputSchemaTypedDict(TypedDict):
    properties: NotRequired[Nullable[Any]]
    required: NotRequired[Nullable[List[str]]]
    type: NotRequired[str]


class InputSchema(BaseModel):
    model_config = ConfigDict(
        populate_by_name=True, arbitrary_types_allowed=True, extra="allow"
    )
    __pydantic_extra__: Dict[str, Nullable[Any]] = pydantic.Field(init=False)

    properties: OptionalNullable[Any] = UNSET

    required: OptionalNullable[List[str]] = UNSET

    type: Optional[str] = "object"

    @property
    def additional_properties(self):
        return self.__pydantic_extra__

    @additional_properties.setter
    def additional_properties(self, value):
        self.__pydantic_extra__ = value  # pyright: ignore[reportIncompatibleVariableOverride]

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = ["properties", "required", "type"]
        nullable_fields = ["properties", "required"]
        null_default_fields = []

        serialized = handler(self)

        m = {}

        for n, f in type(self).model_fields.items():
            k = f.alias or n
            val = serialized.get(k)
            serialized.pop(k, None)

            optional_nullable = k in optional_fields and k in nullable_fields
            is_set = (
                self.__pydantic_fields_set__.intersection({n})
                or k in null_default_fields
            )  # pylint: disable=no-member

            if val is not None and val != UNSET_SENTINEL:
                m[k] = val
            elif val != UNSET_SENTINEL and (
                not k in optional_fields or (optional_nullable and is_set)
            ):
                m[k] = val

        for k, v in serialized.items():
            m[k] = v

        return m


ToolTypeCustom = Literal["custom",]


class ToolCustomTypedDict(TypedDict):
    input_schema: InputSchemaTypedDict
    name: str
    cache_control: NotRequired[AnthropicCacheControlDirectiveTypedDict]
    r"""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."""
    description: NotRequired[str]
    type: NotRequired[ToolTypeCustom]


class ToolCustom(BaseModel):
    input_schema: InputSchema

    name: str

    cache_control: Optional[AnthropicCacheControlDirective] = None
    r"""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."""

    description: Optional[str] = None

    type: Optional[ToolTypeCustom] = None


MessagesRequestToolUnionTypedDict = TypeAliasType(
    "MessagesRequestToolUnionTypedDict",
    Union[
        ChatSearchModelsServerToolTypedDict,
        BashServerToolTypedDict,
        DatetimeServerToolTypedDict,
        ImageGenerationServerToolOpenRouterTypedDict,
        WebFetchServerToolTypedDict,
        OpenRouterWebSearchServerToolTypedDict,
        MessagesRequestToolTypedDict,
        ToolBash20250124TypedDict,
        ToolTextEditor20250124TypedDict,
        ToolCustomTypedDict,
        ToolWebSearch20250305TypedDict,
        ToolWebSearch20260209TypedDict,
        ToolAdvisor20260301TypedDict,
    ],
)


MessagesRequestToolUnion = TypeAliasType(
    "MessagesRequestToolUnion",
    Union[
        ChatSearchModelsServerTool,
        BashServerTool,
        DatetimeServerTool,
        ImageGenerationServerToolOpenRouter,
        WebFetchServerTool,
        OpenRouterWebSearchServerTool,
        MessagesRequestTool,
        ToolBash20250124,
        ToolTextEditor20250124,
        ToolCustom,
        ToolWebSearch20250305,
        ToolWebSearch20260209,
        ToolAdvisor20260301,
    ],
)


class MessagesRequestTypedDict(TypedDict):
    r"""Request schema for Anthropic Messages API endpoint"""

    messages: Nullable[List[MessagesMessageParamTypedDict]]
    model: str
    cache_control: NotRequired[AnthropicCacheControlDirectiveTypedDict]
    r"""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."""
    context_management: NotRequired[Nullable[ContextManagementTypedDict]]
    fallbacks: NotRequired[Nullable[List[MessagesFallbackParamTypedDict]]]
    r"""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."""
    max_tokens: NotRequired[int]
    metadata: NotRequired[MetadataTypedDict]
    models: NotRequired[List[str]]
    output_config: NotRequired[MessagesOutputConfigTypedDict]
    r"""Configuration for controlling output behavior. Supports the effort parameter and structured output format."""
    plugins: NotRequired[List[MessagesRequestPluginTypedDict]]
    r"""Plugins you want to enable for this request, including their settings."""
    provider: NotRequired[Nullable[ProviderPreferencesTypedDict]]
    r"""When multiple model providers are available, optionally indicate your routing preference."""
    service_tier: NotRequired[str]
    session_id: NotRequired[str]
    r"""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."""
    speed: NotRequired[Nullable[Speed]]
    stop_sequences: NotRequired[List[str]]
    stop_server_tools_when: NotRequired[List[StopServerToolsWhenConditionTypedDict]]
    r"""Stop conditions for the server-tool agent loop. Any condition firing halts the loop (OR logic). When set, this overrides `max_tool_calls`."""
    stream: NotRequired[bool]
    system: NotRequired[SystemTypedDict]
    temperature: NotRequired[float]
    thinking: NotRequired[ThinkingTypedDict]
    tool_choice: NotRequired[ToolChoiceTypedDict]
    tools: NotRequired[List[MessagesRequestToolUnionTypedDict]]
    top_k: NotRequired[int]
    top_p: NotRequired[float]
    trace: NotRequired[TraceConfigTypedDict]
    r"""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."""
    user: NotRequired[str]
    r"""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."""


class MessagesRequest(BaseModel):
    r"""Request schema for Anthropic Messages API endpoint"""

    messages: Nullable[List[MessagesMessageParam]]

    model: str

    cache_control: Optional[AnthropicCacheControlDirective] = None
    r"""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."""

    context_management: OptionalNullable[ContextManagement] = UNSET

    fallbacks: OptionalNullable[List[MessagesFallbackParam]] = UNSET
    r"""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."""

    max_tokens: Optional[int] = None

    metadata: Optional[Metadata] = None

    models: Optional[List[str]] = None

    output_config: Optional[MessagesOutputConfig] = None
    r"""Configuration for controlling output behavior. Supports the effort parameter and structured output format."""

    plugins: Optional[List[MessagesRequestPlugin]] = None
    r"""Plugins you want to enable for this request, including their settings."""

    provider: OptionalNullable[ProviderPreferences] = UNSET
    r"""When multiple model providers are available, optionally indicate your routing preference."""

    service_tier: Optional[str] = None

    session_id: Optional[str] = None
    r"""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."""

    speed: Annotated[
        OptionalNullable[Speed], PlainValidator(validate_open_enum(False))
    ] = UNSET

    stop_sequences: Optional[List[str]] = None

    stop_server_tools_when: Optional[List[StopServerToolsWhenCondition]] = None
    r"""Stop conditions for the server-tool agent loop. Any condition firing halts the loop (OR logic). When set, this overrides `max_tool_calls`."""

    stream: Optional[bool] = None

    system: Optional[System] = None

    temperature: Optional[float] = None

    thinking: Optional[Thinking] = None

    tool_choice: Optional[ToolChoice] = None

    tools: Optional[List[MessagesRequestToolUnion]] = None

    top_k: Optional[int] = None

    top_p: Optional[float] = None

    trace: Optional[TraceConfig] = None
    r"""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."""

    user: Optional[str] = None
    r"""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."""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = [
            "cache_control",
            "context_management",
            "fallbacks",
            "max_tokens",
            "metadata",
            "models",
            "output_config",
            "plugins",
            "provider",
            "service_tier",
            "session_id",
            "speed",
            "stop_sequences",
            "stop_server_tools_when",
            "stream",
            "system",
            "temperature",
            "thinking",
            "tool_choice",
            "tools",
            "top_k",
            "top_p",
            "trace",
            "user",
        ]
        nullable_fields = [
            "context_management",
            "fallbacks",
            "messages",
            "provider",
            "speed",
        ]
        null_default_fields = []

        serialized = handler(self)

        m = {}

        for n, f in type(self).model_fields.items():
            k = f.alias or n
            val = serialized.get(k)
            serialized.pop(k, None)

            optional_nullable = k in optional_fields and k in nullable_fields
            is_set = (
                self.__pydantic_fields_set__.intersection({n})
                or k in null_default_fields
            )  # pylint: disable=no-member

            if val is not None and val != UNSET_SENTINEL:
                m[k] = val
            elif val != UNSET_SENTINEL and (
                not k in optional_fields or (optional_nullable and is_set)
            ):
                m[k] = val

        return m
