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

from __future__ import annotations
from .responseoutputitem import ResponseOutputItem, ResponseOutputItemTypedDict
from .responsetool import ResponseTool, ResponseToolTypedDict
from .responseusage import ResponseUsage, ResponseUsageTypedDict
import pydantic
from pydantic import model_serializer
from pydantic.functional_validators import AfterValidator
from r9s.types import BaseModel, Nullable, OptionalNullable, UNSET, UNSET_SENTINEL
from r9s.utils import validate_const
from typing import Any, Dict, List, Literal, Optional, Union
from typing_extensions import Annotated, NotRequired, TypeAliasType, TypedDict


Status = Literal[
    "in_progress",
    "completed",
    "incomplete",
    "failed",
    "cancelled",
]
r"""The status of the response"""


Payer = Literal[
    "developer",
    "organization",
]
r"""Who is paying for this response"""


class BillingTypedDict(TypedDict):
    r"""Billing information"""

    payer: NotRequired[Payer]
    r"""Who is paying for this response"""


class Billing(BaseModel):
    r"""Billing information"""

    payer: Optional[Payer] = None
    r"""Who is paying for this response"""


class ErrorTypedDict(TypedDict):
    pass


class Error(BaseModel):
    pass


class IncompleteDetailsTypedDict(TypedDict):
    pass


class IncompleteDetails(BaseModel):
    pass


ResponseObjectEffort = Literal[
    "none",
    "minimal",
    "low",
    "medium",
    "high",
    "xhigh",
]


class ResponseObjectReasoningTypedDict(TypedDict):
    r"""Reasoning configuration"""

    effort: NotRequired[Nullable[ResponseObjectEffort]]
    r"""Reasoning effort level (none/minimal for fast, low/medium for balanced, high/xhigh for thorough)"""
    summary: NotRequired[Nullable[str]]
    r"""Summary of reasoning"""


class ResponseObjectReasoning(BaseModel):
    r"""Reasoning configuration"""

    effort: OptionalNullable[ResponseObjectEffort] = UNSET
    r"""Reasoning effort level (none/minimal for fast, low/medium for balanced, high/xhigh for thorough)"""

    summary: OptionalNullable[str] = UNSET
    r"""Summary of reasoning"""

    @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


ResponseObjectServiceTier = Literal[
    "auto",
    "default",
]
r"""Service tier used"""


ResponseObjectType = Literal[
    "text",
    "json_object",
    "json_schema",
]


class ResponseObjectFormatTypedDict(TypedDict):
    type: NotRequired[ResponseObjectType]


class ResponseObjectFormat(BaseModel):
    type: Optional[ResponseObjectType] = None


ResponseObjectVerbosity = Literal[
    "low",
    "medium",
    "high",
]
r"""Verbosity level"""


class ResponseObjectTextTypedDict(TypedDict):
    r"""Text format configuration"""

    format_: NotRequired[ResponseObjectFormatTypedDict]
    verbosity: NotRequired[ResponseObjectVerbosity]
    r"""Verbosity level"""


class ResponseObjectText(BaseModel):
    r"""Text format configuration"""

    format_: Annotated[
        Optional[ResponseObjectFormat], pydantic.Field(alias="format")
    ] = None

    verbosity: Optional[ResponseObjectVerbosity] = None
    r"""Verbosity level"""


class ResponseObject2TypedDict(TypedDict):
    pass


class ResponseObject2(BaseModel):
    pass


ResponseObject1 = Literal[
    "none",
    "auto",
    "required",
]


ResponseObjectToolChoiceTypedDict = TypeAliasType(
    "ResponseObjectToolChoiceTypedDict",
    Union[ResponseObject2TypedDict, ResponseObject1],
)
r"""Tool choice strategy used"""


ResponseObjectToolChoice = TypeAliasType(
    "ResponseObjectToolChoice", Union[ResponseObject2, ResponseObject1]
)
r"""Tool choice strategy used"""


ResponseObjectTruncation = Literal[
    "auto",
    "disabled",
]
r"""Truncation strategy used"""


class ResponseObjectTypedDict(TypedDict):
    id: str
    r"""Unique identifier for the response"""
    created_at: int
    r"""Unix timestamp when the response was created"""
    status: Status
    r"""The status of the response"""
    model: str
    r"""The model used for the response"""
    object: Literal["response"]
    background: NotRequired[bool]
    r"""Whether the response is running in the background"""
    billing: NotRequired[BillingTypedDict]
    r"""Billing information"""
    completed_at: NotRequired[Nullable[int]]
    r"""Unix timestamp when the response was completed"""
    error: NotRequired[Nullable[ErrorTypedDict]]
    r"""Error information if the response failed"""
    incomplete_details: NotRequired[Nullable[IncompleteDetailsTypedDict]]
    r"""Details about why the response is incomplete"""
    instructions: NotRequired[str]
    r"""System-level instructions that guided the model's behavior"""
    max_output_tokens: NotRequired[int]
    r"""Maximum number of tokens to generate"""
    max_tool_calls: NotRequired[Nullable[int]]
    r"""Maximum number of tool calls allowed"""
    output: NotRequired[List[ResponseOutputItemTypedDict]]
    r"""Array of output items produced by the model"""
    parallel_tool_calls: NotRequired[bool]
    r"""Whether parallel tool calls are enabled"""
    previous_response_id: NotRequired[Nullable[str]]
    r"""ID of the previous response in a chain"""
    prompt_cache_key: NotRequired[Nullable[str]]
    r"""Key for prompt caching"""
    prompt_cache_retention: NotRequired[Nullable[str]]
    r"""Prompt cache retention policy"""
    reasoning: NotRequired[ResponseObjectReasoningTypedDict]
    r"""Reasoning configuration"""
    safety_identifier: NotRequired[Nullable[str]]
    r"""Safety identifier for the response"""
    service_tier: NotRequired[ResponseObjectServiceTier]
    r"""Service tier used"""
    store: NotRequired[bool]
    r"""Whether to store the response"""
    temperature: NotRequired[float]
    r"""Temperature parameter used"""
    text: NotRequired[ResponseObjectTextTypedDict]
    r"""Text format configuration"""
    tool_choice: NotRequired[ResponseObjectToolChoiceTypedDict]
    r"""Tool choice strategy used"""
    tools: NotRequired[List[ResponseToolTypedDict]]
    r"""Tools that were available"""
    top_logprobs: NotRequired[int]
    r"""Number of top log probabilities"""
    top_p: NotRequired[float]
    r"""Top-p sampling parameter used"""
    truncation: NotRequired[ResponseObjectTruncation]
    r"""Truncation strategy used"""
    user: NotRequired[Nullable[str]]
    r"""User identifier"""
    metadata: NotRequired[Dict[str, Any]]
    r"""Additional metadata"""
    usage: NotRequired[ResponseUsageTypedDict]


class ResponseObject(BaseModel):
    id: str
    r"""Unique identifier for the response"""

    created_at: int
    r"""Unix timestamp when the response was created"""

    status: Status
    r"""The status of the response"""

    model: str
    r"""The model used for the response"""

    OBJECT: Annotated[
        Annotated[Literal["response"], AfterValidator(validate_const("response"))],
        pydantic.Field(alias="object"),
    ] = "response"

    background: Optional[bool] = None
    r"""Whether the response is running in the background"""

    billing: Optional[Billing] = None
    r"""Billing information"""

    completed_at: OptionalNullable[int] = UNSET
    r"""Unix timestamp when the response was completed"""

    error: OptionalNullable[Error] = UNSET
    r"""Error information if the response failed"""

    incomplete_details: OptionalNullable[IncompleteDetails] = UNSET
    r"""Details about why the response is incomplete"""

    instructions: Optional[str] = None
    r"""System-level instructions that guided the model's behavior"""

    max_output_tokens: Optional[int] = None
    r"""Maximum number of tokens to generate"""

    max_tool_calls: OptionalNullable[int] = UNSET
    r"""Maximum number of tool calls allowed"""

    output: Optional[List[ResponseOutputItem]] = None
    r"""Array of output items produced by the model"""

    parallel_tool_calls: Optional[bool] = None
    r"""Whether parallel tool calls are enabled"""

    previous_response_id: OptionalNullable[str] = UNSET
    r"""ID of the previous response in a chain"""

    prompt_cache_key: OptionalNullable[str] = UNSET
    r"""Key for prompt caching"""

    prompt_cache_retention: OptionalNullable[str] = UNSET
    r"""Prompt cache retention policy"""

    reasoning: Optional[ResponseObjectReasoning] = None
    r"""Reasoning configuration"""

    safety_identifier: OptionalNullable[str] = UNSET
    r"""Safety identifier for the response"""

    service_tier: Optional[ResponseObjectServiceTier] = None
    r"""Service tier used"""

    store: Optional[bool] = None
    r"""Whether to store the response"""

    temperature: Optional[float] = None
    r"""Temperature parameter used"""

    text: Optional[ResponseObjectText] = None
    r"""Text format configuration"""

    tool_choice: Optional[ResponseObjectToolChoice] = None
    r"""Tool choice strategy used"""

    tools: Optional[List[ResponseTool]] = None
    r"""Tools that were available"""

    top_logprobs: Optional[int] = None
    r"""Number of top log probabilities"""

    top_p: Optional[float] = None
    r"""Top-p sampling parameter used"""

    truncation: Optional[ResponseObjectTruncation] = None
    r"""Truncation strategy used"""

    user: OptionalNullable[str] = UNSET
    r"""User identifier"""

    metadata: Optional[Dict[str, Any]] = None
    r"""Additional metadata"""

    usage: Optional[ResponseUsage] = None

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