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

from __future__ import annotations
from ._schema10 import Schema10, Schema10TypedDict
from ._schema17 import Schema17, Schema17TypedDict
from ._schema5 import Schema5, Schema5TypedDict
from .chatstreamoptions import ChatStreamOptions, ChatStreamOptionsTypedDict
from .message import Message, MessageTypedDict
from .providersortunion import ProviderSortUnion, ProviderSortUnionTypedDict
from .reasoningsummaryverbosity import ReasoningSummaryVerbosity
from .responseformatjsonschema import (
    ResponseFormatJSONSchema,
    ResponseFormatJSONSchemaTypedDict,
)
from .responseformattextgrammar import (
    ResponseFormatTextGrammar,
    ResponseFormatTextGrammarTypedDict,
)
from .tooldefinitionjson import ToolDefinitionJSON, ToolDefinitionJSONTypedDict
from openrouter.types import (
    BaseModel,
    Nullable,
    OptionalNullable,
    UNSET,
    UNSET_SENTINEL,
    UnrecognizedStr,
)
from openrouter.utils import get_discriminator, validate_const, validate_open_enum
import pydantic
from pydantic import Discriminator, Tag, model_serializer
from pydantic.functional_validators import AfterValidator, PlainValidator
from typing import Any, Dict, List, Literal, Optional, Union
from typing_extensions import Annotated, NotRequired, TypeAliasType, TypedDict


Schema3 = Union[
    Literal[
        "deny",
        "allow",
    ],
    UnrecognizedStr,
]


Schema8 = Union[
    Literal[
        "int4",
        "int8",
        "fp4",
        "fp6",
        "fp8",
        "fp16",
        "bf16",
        "fp32",
        "unknown",
    ],
    UnrecognizedStr,
]


class Schema15TypedDict(TypedDict):
    p50: NotRequired[Nullable[float]]
    p75: NotRequired[Nullable[float]]
    p90: NotRequired[Nullable[float]]
    p99: NotRequired[Nullable[float]]


class Schema15(BaseModel):
    p50: OptionalNullable[float] = UNSET

    p75: OptionalNullable[float] = UNSET

    p90: OptionalNullable[float] = UNSET

    p99: OptionalNullable[float] = UNSET

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = ["p50", "p75", "p90", "p99"]
        nullable_fields = ["p50", "p75", "p90", "p99"]
        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


Schema15UnionTypedDict = TypeAliasType(
    "Schema15UnionTypedDict", Union[Schema15TypedDict, float]
)


Schema15Union = TypeAliasType("Schema15Union", Union[Schema15, float])


class Schema0TypedDict(TypedDict):
    allow_fallbacks: NotRequired[Nullable[bool]]
    require_parameters: NotRequired[Nullable[bool]]
    data_collection: NotRequired[Nullable[Schema3]]
    zdr: NotRequired[Nullable[bool]]
    enforce_distillable_text: NotRequired[Nullable[bool]]
    order: NotRequired[Nullable[List[Schema5TypedDict]]]
    only: NotRequired[Nullable[List[Schema5TypedDict]]]
    ignore: NotRequired[Nullable[List[Schema5TypedDict]]]
    quantizations: NotRequired[Nullable[List[Schema8]]]
    sort: NotRequired[Nullable[ProviderSortUnionTypedDict]]
    max_price: NotRequired[Schema10TypedDict]
    preferred_min_throughput: NotRequired[Nullable[Schema15UnionTypedDict]]
    preferred_max_latency: NotRequired[Nullable[Schema15UnionTypedDict]]


class Schema0(BaseModel):
    allow_fallbacks: OptionalNullable[bool] = UNSET

    require_parameters: OptionalNullable[bool] = UNSET

    data_collection: Annotated[
        OptionalNullable[Schema3], PlainValidator(validate_open_enum(False))
    ] = UNSET

    zdr: OptionalNullable[bool] = UNSET

    enforce_distillable_text: OptionalNullable[bool] = UNSET

    order: OptionalNullable[List[Schema5]] = UNSET

    only: OptionalNullable[List[Schema5]] = UNSET

    ignore: OptionalNullable[List[Schema5]] = UNSET

    quantizations: OptionalNullable[
        List[Annotated[Schema8, PlainValidator(validate_open_enum(False))]]
    ] = UNSET

    sort: OptionalNullable[ProviderSortUnion] = UNSET

    max_price: Optional[Schema10] = None

    preferred_min_throughput: OptionalNullable[Schema15Union] = UNSET

    preferred_max_latency: OptionalNullable[Schema15Union] = UNSET

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = [
            "allow_fallbacks",
            "require_parameters",
            "data_collection",
            "zdr",
            "enforce_distillable_text",
            "order",
            "only",
            "ignore",
            "quantizations",
            "sort",
            "max_price",
            "preferred_min_throughput",
            "preferred_max_latency",
        ]
        nullable_fields = [
            "allow_fallbacks",
            "require_parameters",
            "data_collection",
            "zdr",
            "enforce_distillable_text",
            "order",
            "only",
            "ignore",
            "quantizations",
            "sort",
            "preferred_min_throughput",
            "preferred_max_latency",
        ]
        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


Route = Union[
    Literal[
        "fallback",
        "sort",
    ],
    UnrecognizedStr,
]


Effort = Union[
    Literal[
        "xhigh",
        "high",
        "medium",
        "low",
        "minimal",
        "none",
    ],
    UnrecognizedStr,
]


class ReasoningTypedDict(TypedDict):
    effort: NotRequired[Nullable[Effort]]
    summary: NotRequired[Nullable[ReasoningSummaryVerbosity]]


class Reasoning(BaseModel):
    effort: Annotated[
        OptionalNullable[Effort], PlainValidator(validate_open_enum(False))
    ] = UNSET

    summary: Annotated[
        OptionalNullable[ReasoningSummaryVerbosity],
        PlainValidator(validate_open_enum(False)),
    ] = UNSET

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = ["effort", "summary"]
        nullable_fields = ["effort", "summary"]
        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


class ResponseFormatPythonTypedDict(TypedDict):
    type: Literal["python"]


class ResponseFormatPython(BaseModel):
    TYPE: Annotated[
        Annotated[Literal["python"], AfterValidator(validate_const("python"))],
        pydantic.Field(alias="type"),
    ] = "python"


class ResponseFormatJSONObjectTypedDict(TypedDict):
    type: Literal["json_object"]


class ResponseFormatJSONObject(BaseModel):
    TYPE: Annotated[
        Annotated[
            Literal["json_object"], AfterValidator(validate_const("json_object"))
        ],
        pydantic.Field(alias="type"),
    ] = "json_object"


class ResponseFormatTextTypedDict(TypedDict):
    type: Literal["text"]


class ResponseFormatText(BaseModel):
    TYPE: Annotated[
        Annotated[Literal["text"], AfterValidator(validate_const("text"))],
        pydantic.Field(alias="type"),
    ] = "text"


ResponseFormatTypedDict = TypeAliasType(
    "ResponseFormatTypedDict",
    Union[
        ResponseFormatTextTypedDict,
        ResponseFormatJSONObjectTypedDict,
        ResponseFormatPythonTypedDict,
        ResponseFormatJSONSchemaTypedDict,
        ResponseFormatTextGrammarTypedDict,
    ],
)


ResponseFormat = Annotated[
    Union[
        Annotated[ResponseFormatText, Tag("text")],
        Annotated[ResponseFormatJSONObject, Tag("json_object")],
        Annotated[ResponseFormatJSONSchema, Tag("json_schema")],
        Annotated[ResponseFormatTextGrammar, Tag("grammar")],
        Annotated[ResponseFormatPython, Tag("python")],
    ],
    Discriminator(lambda m: get_discriminator(m, "type", "type")),
]


StopTypedDict = TypeAliasType("StopTypedDict", Union[str, List[str]])


Stop = TypeAliasType("Stop", Union[str, List[str]])


class DebugTypedDict(TypedDict):
    echo_upstream_body: NotRequired[bool]


class Debug(BaseModel):
    echo_upstream_body: Optional[bool] = None


ChatGenerationParamsImageConfigTypedDict = TypeAliasType(
    "ChatGenerationParamsImageConfigTypedDict", Union[str, float, List[Any]]
)


ChatGenerationParamsImageConfig = TypeAliasType(
    "ChatGenerationParamsImageConfig", Union[str, float, List[Any]]
)


Modality = Union[
    Literal[
        "text",
        "image",
    ],
    UnrecognizedStr,
]


class ChatGenerationParamsTypedDict(TypedDict):
    messages: List[MessageTypedDict]
    provider: NotRequired[Nullable[Schema0TypedDict]]
    plugins: NotRequired[List[Schema17TypedDict]]
    route: NotRequired[Nullable[Route]]
    user: NotRequired[str]
    session_id: NotRequired[str]
    model: NotRequired[str]
    models: NotRequired[List[str]]
    frequency_penalty: NotRequired[Nullable[float]]
    logit_bias: NotRequired[Nullable[Dict[str, float]]]
    logprobs: NotRequired[Nullable[bool]]
    top_logprobs: NotRequired[Nullable[float]]
    max_completion_tokens: NotRequired[Nullable[float]]
    max_tokens: NotRequired[Nullable[float]]
    metadata: NotRequired[Dict[str, str]]
    presence_penalty: NotRequired[Nullable[float]]
    reasoning: NotRequired[ReasoningTypedDict]
    response_format: NotRequired[ResponseFormatTypedDict]
    seed: NotRequired[Nullable[int]]
    stop: NotRequired[Nullable[StopTypedDict]]
    stream: NotRequired[bool]
    stream_options: NotRequired[Nullable[ChatStreamOptionsTypedDict]]
    temperature: NotRequired[Nullable[float]]
    tool_choice: NotRequired[Any]
    tools: NotRequired[List[ToolDefinitionJSONTypedDict]]
    top_p: NotRequired[Nullable[float]]
    debug: NotRequired[DebugTypedDict]
    image_config: NotRequired[Dict[str, ChatGenerationParamsImageConfigTypedDict]]
    modalities: NotRequired[List[Modality]]


class ChatGenerationParams(BaseModel):
    messages: List[Message]

    provider: OptionalNullable[Schema0] = UNSET

    plugins: Optional[List[Schema17]] = None

    route: Annotated[
        OptionalNullable[Route], PlainValidator(validate_open_enum(False))
    ] = UNSET

    user: Optional[str] = None

    session_id: Optional[str] = None

    model: Optional[str] = None

    models: Optional[List[str]] = None

    frequency_penalty: OptionalNullable[float] = UNSET

    logit_bias: OptionalNullable[Dict[str, float]] = UNSET

    logprobs: OptionalNullable[bool] = UNSET

    top_logprobs: OptionalNullable[float] = UNSET

    max_completion_tokens: OptionalNullable[float] = UNSET

    max_tokens: OptionalNullable[float] = UNSET

    metadata: Optional[Dict[str, str]] = None

    presence_penalty: OptionalNullable[float] = UNSET

    reasoning: Optional[Reasoning] = None

    response_format: Optional[ResponseFormat] = None

    seed: OptionalNullable[int] = UNSET

    stop: OptionalNullable[Stop] = UNSET

    stream: Optional[bool] = False

    stream_options: OptionalNullable[ChatStreamOptions] = UNSET

    temperature: OptionalNullable[float] = UNSET

    tool_choice: Optional[Any] = None

    tools: Optional[List[ToolDefinitionJSON]] = None

    top_p: OptionalNullable[float] = UNSET

    debug: Optional[Debug] = None

    image_config: Optional[Dict[str, ChatGenerationParamsImageConfig]] = None

    modalities: Optional[
        List[Annotated[Modality, PlainValidator(validate_open_enum(False))]]
    ] = None

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = [
            "provider",
            "plugins",
            "route",
            "user",
            "session_id",
            "model",
            "models",
            "frequency_penalty",
            "logit_bias",
            "logprobs",
            "top_logprobs",
            "max_completion_tokens",
            "max_tokens",
            "metadata",
            "presence_penalty",
            "reasoning",
            "response_format",
            "seed",
            "stop",
            "stream",
            "stream_options",
            "temperature",
            "tool_choice",
            "tools",
            "top_p",
            "debug",
            "image_config",
            "modalities",
        ]
        nullable_fields = [
            "provider",
            "route",
            "frequency_penalty",
            "logit_bias",
            "logprobs",
            "top_logprobs",
            "max_completion_tokens",
            "max_tokens",
            "presence_penalty",
            "seed",
            "stop",
            "stream_options",
            "temperature",
            "top_p",
        ]
        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
