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

from __future__ import annotations
from .anthropiccachecontroldirective import (
    AnthropicCacheControlDirective,
    AnthropicCacheControlDirectiveTypedDict,
)
from .autorouterplugin import AutoRouterPlugin, AutoRouterPluginTypedDict
from .chatdebugoptions import ChatDebugOptions, ChatDebugOptionsTypedDict
from .chatformatgrammarconfig import (
    ChatFormatGrammarConfig,
    ChatFormatGrammarConfigTypedDict,
)
from .chatformatjsonschemaconfig import (
    ChatFormatJSONSchemaConfig,
    ChatFormatJSONSchemaConfigTypedDict,
)
from .chatformatpythonconfig import (
    ChatFormatPythonConfig,
    ChatFormatPythonConfigTypedDict,
)
from .chatformattextconfig import ChatFormatTextConfig, ChatFormatTextConfigTypedDict
from .chatfunctiontool import ChatFunctionTool, ChatFunctionToolTypedDict
from .chatmessages import ChatMessages, ChatMessagesTypedDict
from .chatreasoningsummaryverbosityenum import ChatReasoningSummaryVerbosityEnum
from .chatstreamoptions import ChatStreamOptions, ChatStreamOptionsTypedDict
from .chattoolchoice import ChatToolChoice, ChatToolChoiceTypedDict
from .contextcompressionplugin import (
    ContextCompressionPlugin,
    ContextCompressionPluginTypedDict,
)
from .fileparserplugin import FileParserPlugin, FileParserPluginTypedDict
from .formatjsonobjectconfig import (
    FormatJSONObjectConfig,
    FormatJSONObjectConfigTypedDict,
)
from .fusionplugin import FusionPlugin, FusionPluginTypedDict
from .imageconfig import ImageConfig, ImageConfigTypedDict
from .moderationplugin import ModerationPlugin, ModerationPluginTypedDict
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 .websearchplugin import WebSearchPlugin, WebSearchPluginTypedDict
from openrouter.types import (
    BaseModel,
    Nullable,
    OptionalNullable,
    UNSET,
    UNSET_SENTINEL,
    UnrecognizedStr,
)
from openrouter.utils import get_discriminator, validate_open_enum
from pydantic import 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


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


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


ChatRequestPlugin = 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")),
]


ChatRequestEffort = Union[
    Literal[
        "xhigh",
        "high",
        "medium",
        "low",
        "minimal",
        "none",
    ],
    UnrecognizedStr,
]
r"""Constrains effort on reasoning for reasoning models"""


class ChatRequestReasoningTypedDict(TypedDict):
    r"""Configuration options for reasoning models"""

    effort: NotRequired[Nullable[ChatRequestEffort]]
    r"""Constrains effort on reasoning for reasoning models"""
    summary: NotRequired[Nullable[ChatReasoningSummaryVerbosityEnum]]


class ChatRequestReasoning(BaseModel):
    r"""Configuration options for reasoning models"""

    effort: Annotated[
        OptionalNullable[ChatRequestEffort], PlainValidator(validate_open_enum(False))
    ] = UNSET
    r"""Constrains effort on reasoning for reasoning models"""

    summary: Annotated[
        OptionalNullable[ChatReasoningSummaryVerbosityEnum],
        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


ChatRequestReasoningEffort = Union[
    Literal[
        "xhigh",
        "high",
        "medium",
        "low",
        "minimal",
        "none",
    ],
    UnrecognizedStr,
]
r"""Shorthand for setting reasoning effort. Equivalent to setting reasoning.effort. Cannot be used simultaneously with reasoning.effort if they differ."""


ResponseFormatTypedDict = TypeAliasType(
    "ResponseFormatTypedDict",
    Union[
        ChatFormatTextConfigTypedDict,
        FormatJSONObjectConfigTypedDict,
        ChatFormatPythonConfigTypedDict,
        ChatFormatJSONSchemaConfigTypedDict,
        ChatFormatGrammarConfigTypedDict,
    ],
)
r"""Response format configuration"""


ResponseFormat = Annotated[
    Union[
        Annotated[ChatFormatGrammarConfig, Tag("grammar")],
        Annotated[FormatJSONObjectConfig, Tag("json_object")],
        Annotated[ChatFormatJSONSchemaConfig, Tag("json_schema")],
        Annotated[ChatFormatPythonConfig, Tag("python")],
        Annotated[ChatFormatTextConfig, Tag("text")],
    ],
    Discriminator(lambda m: get_discriminator(m, "type", "type")),
]
r"""Response format configuration"""


ChatRequestServiceTier = Union[
    Literal[
        "auto",
        "default",
        "flex",
        "priority",
        "scale",
    ],
    UnrecognizedStr,
]
r"""The service tier to use for processing this request."""


StopTypedDict = TypeAliasType("StopTypedDict", Union[str, List[str], Any])
r"""Stop sequences (up to 4)"""


Stop = TypeAliasType("Stop", Union[str, List[str], Any])
r"""Stop sequences (up to 4)"""


class ChatRequestTypedDict(TypedDict):
    r"""Chat completion request parameters"""

    messages: List[ChatMessagesTypedDict]
    r"""List of messages for the conversation"""
    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."""
    debug: NotRequired[ChatDebugOptionsTypedDict]
    r"""Debug options for inspecting request transformations (streaming only)"""
    frequency_penalty: NotRequired[Nullable[float]]
    r"""Frequency penalty (-2.0 to 2.0)"""
    image_config: NotRequired[Dict[str, ImageConfigTypedDict]]
    r"""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."""
    logit_bias: NotRequired[Nullable[Dict[str, float]]]
    r"""Token logit bias adjustments"""
    logprobs: NotRequired[Nullable[bool]]
    r"""Return log probabilities"""
    max_completion_tokens: NotRequired[Nullable[int]]
    r"""Maximum tokens in completion"""
    max_tokens: NotRequired[Nullable[int]]
    r"""Maximum tokens (deprecated, use max_completion_tokens). Note: some providers enforce a minimum of 16."""
    metadata: NotRequired[Dict[str, str]]
    r"""Key-value pairs for additional object information (max 16 pairs, 64 char keys, 512 char values)"""
    min_p: NotRequired[Nullable[float]]
    r"""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."""
    modalities: NotRequired[List[Modality]]
    r"""Output modalities for the response. Supported values are \"text\", \"image\", and \"audio\"."""
    model: NotRequired[str]
    r"""Model to use for completion"""
    models: NotRequired[List[str]]
    r"""Models to use for completion"""
    parallel_tool_calls: NotRequired[Nullable[bool]]
    r"""Whether to enable parallel function calling during tool use. When true, the model may generate multiple tool calls in a single response."""
    plugins: NotRequired[List[ChatRequestPluginTypedDict]]
    r"""Plugins you want to enable for this request, including their settings."""
    presence_penalty: NotRequired[Nullable[float]]
    r"""Presence penalty (-2.0 to 2.0)"""
    provider: NotRequired[Nullable[ProviderPreferencesTypedDict]]
    r"""When multiple model providers are available, optionally indicate your routing preference."""
    reasoning: NotRequired[ChatRequestReasoningTypedDict]
    r"""Configuration options for reasoning models"""
    reasoning_effort: NotRequired[Nullable[ChatRequestReasoningEffort]]
    r"""Shorthand for setting reasoning effort. Equivalent to setting reasoning.effort. Cannot be used simultaneously with reasoning.effort if they differ."""
    repetition_penalty: NotRequired[Nullable[float]]
    r"""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."""
    response_format: NotRequired[ResponseFormatTypedDict]
    r"""Response format configuration"""
    seed: NotRequired[Nullable[int]]
    r"""Random seed for deterministic outputs"""
    service_tier: NotRequired[Nullable[ChatRequestServiceTier]]
    r"""The service tier to use for processing this request."""
    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."""
    stop: NotRequired[Nullable[StopTypedDict]]
    r"""Stop sequences (up to 4)"""
    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]
    r"""Enable streaming response"""
    stream_options: NotRequired[Nullable[ChatStreamOptionsTypedDict]]
    r"""Streaming configuration options"""
    temperature: NotRequired[Nullable[float]]
    r"""Sampling temperature (0-2)"""
    tool_choice: NotRequired[ChatToolChoiceTypedDict]
    r"""Tool choice configuration"""
    tools: NotRequired[List[ChatFunctionToolTypedDict]]
    r"""Available tools for function calling"""
    top_a: NotRequired[Nullable[float]]
    r"""Consider only tokens with \"sufficiently high\" probabilities based on the probability of the most likely token. Not all providers support this parameter."""
    top_k: NotRequired[Nullable[int]]
    r"""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."""
    top_logprobs: NotRequired[Nullable[int]]
    r"""Number of top log probabilities to return (0-20)"""
    top_p: NotRequired[Nullable[float]]
    r"""Nucleus sampling parameter (0-1)"""
    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"""Unique user identifier"""


class ChatRequest(BaseModel):
    r"""Chat completion request parameters"""

    messages: List[ChatMessages]
    r"""List of messages for the conversation"""

    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."""

    debug: Optional[ChatDebugOptions] = None
    r"""Debug options for inspecting request transformations (streaming only)"""

    frequency_penalty: OptionalNullable[float] = UNSET
    r"""Frequency penalty (-2.0 to 2.0)"""

    image_config: Optional[Dict[str, ImageConfig]] = None
    r"""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."""

    logit_bias: OptionalNullable[Dict[str, float]] = UNSET
    r"""Token logit bias adjustments"""

    logprobs: OptionalNullable[bool] = UNSET
    r"""Return log probabilities"""

    max_completion_tokens: OptionalNullable[int] = UNSET
    r"""Maximum tokens in completion"""

    max_tokens: OptionalNullable[int] = UNSET
    r"""Maximum tokens (deprecated, use max_completion_tokens). Note: some providers enforce a minimum of 16."""

    metadata: Optional[Dict[str, str]] = None
    r"""Key-value pairs for additional object information (max 16 pairs, 64 char keys, 512 char values)"""

    min_p: OptionalNullable[float] = UNSET
    r"""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."""

    modalities: Optional[
        List[Annotated[Modality, PlainValidator(validate_open_enum(False))]]
    ] = None
    r"""Output modalities for the response. Supported values are \"text\", \"image\", and \"audio\"."""

    model: Optional[str] = None
    r"""Model to use for completion"""

    models: Optional[List[str]] = None
    r"""Models to use for completion"""

    parallel_tool_calls: OptionalNullable[bool] = UNSET
    r"""Whether to enable parallel function calling during tool use. When true, the model may generate multiple tool calls in a single response."""

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

    presence_penalty: OptionalNullable[float] = UNSET
    r"""Presence penalty (-2.0 to 2.0)"""

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

    reasoning: Optional[ChatRequestReasoning] = None
    r"""Configuration options for reasoning models"""

    reasoning_effort: Annotated[
        OptionalNullable[ChatRequestReasoningEffort],
        PlainValidator(validate_open_enum(False)),
    ] = UNSET
    r"""Shorthand for setting reasoning effort. Equivalent to setting reasoning.effort. Cannot be used simultaneously with reasoning.effort if they differ."""

    repetition_penalty: OptionalNullable[float] = UNSET
    r"""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."""

    response_format: Optional[ResponseFormat] = None
    r"""Response format configuration"""

    seed: OptionalNullable[int] = UNSET
    r"""Random seed for deterministic outputs"""

    service_tier: Annotated[
        OptionalNullable[ChatRequestServiceTier],
        PlainValidator(validate_open_enum(False)),
    ] = UNSET
    r"""The service tier to use for processing this request."""

    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."""

    stop: OptionalNullable[Stop] = UNSET
    r"""Stop sequences (up to 4)"""

    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] = False
    r"""Enable streaming response"""

    stream_options: OptionalNullable[ChatStreamOptions] = UNSET
    r"""Streaming configuration options"""

    temperature: OptionalNullable[float] = UNSET
    r"""Sampling temperature (0-2)"""

    tool_choice: Optional[ChatToolChoice] = None
    r"""Tool choice configuration"""

    tools: Optional[List[ChatFunctionTool]] = None
    r"""Available tools for function calling"""

    top_a: OptionalNullable[float] = UNSET
    r"""Consider only tokens with \"sufficiently high\" probabilities based on the probability of the most likely token. Not all providers support this parameter."""

    top_k: OptionalNullable[int] = UNSET
    r"""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."""

    top_logprobs: OptionalNullable[int] = UNSET
    r"""Number of top log probabilities to return (0-20)"""

    top_p: OptionalNullable[float] = UNSET
    r"""Nucleus sampling parameter (0-1)"""

    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"""Unique user identifier"""

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