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

from __future__ import annotations
from .tmodel import TModel, TModelTypedDict
from opperai.types import BaseModel, Nullable, OptionalNullable, UNSET, UNSET_SENTINEL
from pydantic import model_serializer
from typing import Any, Dict
from typing_extensions import NotRequired, TypedDict


class UpdateFunctionRequestTypedDict(TypedDict):
    name: NotRequired[Nullable[str]]
    r"""The name of the function. Must be unique within the project and can only contain letters, numbers, underscores and hyphens."""
    description: NotRequired[Nullable[str]]
    r"""Optional description of the function. This is used to describe the function to a user."""
    instructions: NotRequired[Nullable[str]]
    r"""The instructions for the function, this is the prompt that will be sent to the model to complete the task. Recommended to be concise and to the point"""
    input_schema: NotRequired[Nullable[Dict[str, Any]]]
    r"""Optional input schema for the function. Can preferably include field descriptions to allow the model to reason about the input variables. Schema is validated against the input data and issues an error if it does not match. With the Opper SDKs you can define these schemas through libraries like Pydantic and Zod. For schemas with definitions, prefer using '$defs' and '#/$defs/...' references."""
    output_schema: NotRequired[Nullable[Dict[str, Any]]]
    r"""Optional output schema for the function. Can preferably include field descriptions to allow the model to reason about the output variables. Schema is validated against the output data and issues an error if it does not match. With the Opper SDKs you can define these schemas through libraries like Pydantic and Zod. For schemas with definitions, prefer using '$defs' and '#/$defs/...' references."""
    model: NotRequired[Nullable[TModelTypedDict]]
    r"""Optionally provide a model to use for completing the task.
    If not provided, a default model will be used. Currently the default model is `azure/gpt-4o-eu`

    To specify options for the model, use a dictionary of key-value pairs. The options are passed to the model on invocation.
    An example of passing temperature to `gpt-4o-mini` hosted on OpenAI is shown below.

    ```json
    {
    \"model\": \"openai/gpt-4o-mini\", # the model name
    \"options\": {
    \"temperature\": 0.5 # the options for the model
    }
    }
    ```

    To specify a fallback model, use a list of models. The models will then be tried in order.
    The second model will be used if the first model is not available, and so on.

    ```json
    [
    \"openai/gpt-4o-mini\", # first model to try
    \"openai/gpt-4.1-nano\", # second model to try
    ]
    ```

    """
    configuration: NotRequired[Nullable[Dict[str, Any]]]
    r"""Optional configuration for the function.Configuration is a dictionary of key-value pairs that can be used to override the default configuration for the function."""


class UpdateFunctionRequest(BaseModel):
    name: OptionalNullable[str] = UNSET
    r"""The name of the function. Must be unique within the project and can only contain letters, numbers, underscores and hyphens."""

    description: OptionalNullable[str] = UNSET
    r"""Optional description of the function. This is used to describe the function to a user."""

    instructions: OptionalNullable[str] = UNSET
    r"""The instructions for the function, this is the prompt that will be sent to the model to complete the task. Recommended to be concise and to the point"""

    input_schema: OptionalNullable[Dict[str, Any]] = UNSET
    r"""Optional input schema for the function. Can preferably include field descriptions to allow the model to reason about the input variables. Schema is validated against the input data and issues an error if it does not match. With the Opper SDKs you can define these schemas through libraries like Pydantic and Zod. For schemas with definitions, prefer using '$defs' and '#/$defs/...' references."""

    output_schema: OptionalNullable[Dict[str, Any]] = UNSET
    r"""Optional output schema for the function. Can preferably include field descriptions to allow the model to reason about the output variables. Schema is validated against the output data and issues an error if it does not match. With the Opper SDKs you can define these schemas through libraries like Pydantic and Zod. For schemas with definitions, prefer using '$defs' and '#/$defs/...' references."""

    model: OptionalNullable[TModel] = UNSET
    r"""Optionally provide a model to use for completing the task.
    If not provided, a default model will be used. Currently the default model is `azure/gpt-4o-eu`

    To specify options for the model, use a dictionary of key-value pairs. The options are passed to the model on invocation.
    An example of passing temperature to `gpt-4o-mini` hosted on OpenAI is shown below.

    ```json
    {
    \"model\": \"openai/gpt-4o-mini\", # the model name
    \"options\": {
    \"temperature\": 0.5 # the options for the model
    }
    }
    ```

    To specify a fallback model, use a list of models. The models will then be tried in order.
    The second model will be used if the first model is not available, and so on.

    ```json
    [
    \"openai/gpt-4o-mini\", # first model to try
    \"openai/gpt-4.1-nano\", # second model to try
    ]
    ```

    """

    configuration: OptionalNullable[Dict[str, Any]] = UNSET
    r"""Optional configuration for the function.Configuration is a dictionary of key-value pairs that can be used to override the default configuration for the function."""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = [
            "name",
            "description",
            "instructions",
            "input_schema",
            "output_schema",
            "model",
            "configuration",
        ]
        nullable_fields = [
            "name",
            "description",
            "instructions",
            "input_schema",
            "output_schema",
            "model",
            "configuration",
        ]
        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
