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

from __future__ import annotations
from .openairesponsesincompletedetails import (
    OpenAIResponsesIncompleteDetails,
    OpenAIResponsesIncompleteDetailsTypedDict,
)
from .openairesponsesinput_union import (
    OpenAIResponsesInputUnion,
    OpenAIResponsesInputUnionTypedDict,
)
from .openairesponsesprompt import OpenAIResponsesPrompt, OpenAIResponsesPromptTypedDict
from .openairesponsesreasoningconfig import (
    OpenAIResponsesReasoningConfig,
    OpenAIResponsesReasoningConfigTypedDict,
)
from .openairesponsesresponsestatus import OpenAIResponsesResponseStatus
from .openairesponsesservicetier import OpenAIResponsesServiceTier
from .openairesponsestoolchoice_union import (
    OpenAIResponsesToolChoiceUnion,
    OpenAIResponsesToolChoiceUnionTypedDict,
)
from .openairesponsestruncation import OpenAIResponsesTruncation
from .openresponsesusage import OpenResponsesUsage, OpenResponsesUsageTypedDict
from .openresponseswebsearch20250826tool import (
    OpenResponsesWebSearch20250826Tool,
    OpenResponsesWebSearch20250826ToolTypedDict,
)
from .openresponseswebsearchpreview20250311tool import (
    OpenResponsesWebSearchPreview20250311Tool,
    OpenResponsesWebSearchPreview20250311ToolTypedDict,
)
from .openresponseswebsearchpreviewtool import (
    OpenResponsesWebSearchPreviewTool,
    OpenResponsesWebSearchPreviewToolTypedDict,
)
from .openresponseswebsearchtool import (
    OpenResponsesWebSearchTool,
    OpenResponsesWebSearchToolTypedDict,
)
from .responseserrorfield import ResponsesErrorField, ResponsesErrorFieldTypedDict
from .responsesoutputitem import ResponsesOutputItem, ResponsesOutputItemTypedDict
from .responsetextconfig import ResponseTextConfig, ResponseTextConfigTypedDict
from openrouter.types import (
    BaseModel,
    Nullable,
    OptionalNullable,
    UNSET,
    UNSET_SENTINEL,
)
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


Object = Literal["response",]


OpenResponsesNonStreamingResponseType = Literal["function",]


class OpenResponsesNonStreamingResponseToolFunctionTypedDict(TypedDict):
    r"""Function tool definition"""

    type: OpenResponsesNonStreamingResponseType
    name: str
    parameters: Nullable[Dict[str, Nullable[Any]]]
    description: NotRequired[Nullable[str]]
    strict: NotRequired[Nullable[bool]]


class OpenResponsesNonStreamingResponseToolFunction(BaseModel):
    r"""Function tool definition"""

    type: OpenResponsesNonStreamingResponseType

    name: str

    parameters: Nullable[Dict[str, Nullable[Any]]]

    description: OptionalNullable[str] = UNSET

    strict: OptionalNullable[bool] = UNSET

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


OpenResponsesNonStreamingResponseToolUnionTypedDict = TypeAliasType(
    "OpenResponsesNonStreamingResponseToolUnionTypedDict",
    Union[
        OpenResponsesWebSearchPreviewToolTypedDict,
        OpenResponsesWebSearchPreview20250311ToolTypedDict,
        OpenResponsesWebSearchToolTypedDict,
        OpenResponsesWebSearch20250826ToolTypedDict,
        OpenResponsesNonStreamingResponseToolFunctionTypedDict,
    ],
)


OpenResponsesNonStreamingResponseToolUnion = Annotated[
    Union[
        Annotated[OpenResponsesNonStreamingResponseToolFunction, Tag("function")],
        Annotated[OpenResponsesWebSearchPreviewTool, Tag("web_search_preview")],
        Annotated[
            OpenResponsesWebSearchPreview20250311Tool,
            Tag("web_search_preview_2025_03_11"),
        ],
        Annotated[OpenResponsesWebSearchTool, Tag("web_search")],
        Annotated[OpenResponsesWebSearch20250826Tool, Tag("web_search_2025_08_26")],
    ],
    Discriminator(lambda m: get_discriminator(m, "type", "type")),
]


class OpenResponsesNonStreamingResponseTypedDict(TypedDict):
    r"""Complete non-streaming response from the Responses API"""

    id: str
    object: Object
    created_at: float
    model: str
    output: List[ResponsesOutputItemTypedDict]
    error: Nullable[ResponsesErrorFieldTypedDict]
    r"""Error information returned from the API"""
    incomplete_details: Nullable[OpenAIResponsesIncompleteDetailsTypedDict]
    temperature: Nullable[float]
    top_p: Nullable[float]
    instructions: Nullable[OpenAIResponsesInputUnionTypedDict]
    metadata: Nullable[Dict[str, str]]
    r"""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."""
    tools: List[OpenResponsesNonStreamingResponseToolUnionTypedDict]
    tool_choice: OpenAIResponsesToolChoiceUnionTypedDict
    parallel_tool_calls: bool
    status: NotRequired[OpenAIResponsesResponseStatus]
    user: NotRequired[Nullable[str]]
    output_text: NotRequired[str]
    prompt_cache_key: NotRequired[Nullable[str]]
    safety_identifier: NotRequired[Nullable[str]]
    usage: NotRequired[OpenResponsesUsageTypedDict]
    r"""Token usage information for the response"""
    max_tool_calls: NotRequired[Nullable[float]]
    top_logprobs: NotRequired[float]
    max_output_tokens: NotRequired[Nullable[float]]
    prompt: NotRequired[Nullable[OpenAIResponsesPromptTypedDict]]
    background: NotRequired[Nullable[bool]]
    previous_response_id: NotRequired[Nullable[str]]
    reasoning: NotRequired[Nullable[OpenAIResponsesReasoningConfigTypedDict]]
    service_tier: NotRequired[Nullable[OpenAIResponsesServiceTier]]
    store: NotRequired[bool]
    truncation: NotRequired[Nullable[OpenAIResponsesTruncation]]
    text: NotRequired[ResponseTextConfigTypedDict]
    r"""Text output configuration including format and verbosity"""


class OpenResponsesNonStreamingResponse(BaseModel):
    r"""Complete non-streaming response from the Responses API"""

    id: str

    object: Object

    created_at: float

    model: str

    output: List[ResponsesOutputItem]

    error: Nullable[ResponsesErrorField]
    r"""Error information returned from the API"""

    incomplete_details: Nullable[OpenAIResponsesIncompleteDetails]

    temperature: Nullable[float]

    top_p: Nullable[float]

    instructions: Nullable[OpenAIResponsesInputUnion]

    metadata: Nullable[Dict[str, str]]
    r"""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."""

    tools: List[OpenResponsesNonStreamingResponseToolUnion]

    tool_choice: OpenAIResponsesToolChoiceUnion

    parallel_tool_calls: bool

    status: Annotated[
        Optional[OpenAIResponsesResponseStatus],
        PlainValidator(validate_open_enum(False)),
    ] = None

    user: OptionalNullable[str] = UNSET

    output_text: Optional[str] = None

    prompt_cache_key: OptionalNullable[str] = UNSET

    safety_identifier: OptionalNullable[str] = UNSET

    usage: Optional[OpenResponsesUsage] = None
    r"""Token usage information for the response"""

    max_tool_calls: OptionalNullable[float] = UNSET

    top_logprobs: Optional[float] = None

    max_output_tokens: OptionalNullable[float] = UNSET

    prompt: OptionalNullable[OpenAIResponsesPrompt] = UNSET

    background: OptionalNullable[bool] = UNSET

    previous_response_id: OptionalNullable[str] = UNSET

    reasoning: OptionalNullable[OpenAIResponsesReasoningConfig] = UNSET

    service_tier: Annotated[
        OptionalNullable[OpenAIResponsesServiceTier],
        PlainValidator(validate_open_enum(False)),
    ] = UNSET

    store: Optional[bool] = None

    truncation: Annotated[
        OptionalNullable[OpenAIResponsesTruncation],
        PlainValidator(validate_open_enum(False)),
    ] = UNSET

    text: Optional[ResponseTextConfig] = None
    r"""Text output configuration including format and verbosity"""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = [
            "status",
            "user",
            "output_text",
            "prompt_cache_key",
            "safety_identifier",
            "usage",
            "max_tool_calls",
            "top_logprobs",
            "max_output_tokens",
            "prompt",
            "background",
            "previous_response_id",
            "reasoning",
            "service_tier",
            "store",
            "truncation",
            "text",
        ]
        nullable_fields = [
            "user",
            "prompt_cache_key",
            "safety_identifier",
            "error",
            "incomplete_details",
            "max_tool_calls",
            "max_output_tokens",
            "temperature",
            "top_p",
            "instructions",
            "metadata",
            "prompt",
            "background",
            "previous_response_id",
            "reasoning",
            "service_tier",
            "truncation",
        ]
        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
