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

from __future__ import annotations
from .example import Example, ExampleTypedDict
from .functioncallconfiguration import (
    FunctionCallConfiguration,
    FunctionCallConfigurationTypedDict,
)
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, List, Optional
from typing_extensions import NotRequired, TypedDict


class AppAPIPublicV2FunctionCallCallFunctionRequestTypedDict(TypedDict):
    name: str
    r"""Provide a unique name of the task. A function with this name will be created in the project. Functions configuration is overridden by the request parameters."""
    instructions: NotRequired[Nullable[str]]
    r"""Optionally provide an instruction for the model to complete the task. Recommended to be concise and to the point"""
    input_schema: NotRequired[Nullable[Dict[str, Any]]]
    r"""Optionally provide an input schema for the task. 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"""Optionally provide an output schema for the task. Response is guaranteed to match the schema or throw an error. Can preferably include field descriptions to allow the model to reason about the output variables. 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."""
    input: NotRequired[Nullable[Any]]
    r"""Optionally provide input data as context to complete the task. Could be a text, image, audio or a combination of these."""
    model: NotRequired[TModelTypedDict]
    examples: NotRequired[Nullable[List[ExampleTypedDict]]]
    r"""Optionally provide examples of successful task completions. Will be added to the prompt to help the model understand the task from examples."""
    parent_span_id: NotRequired[Nullable[str]]
    r"""Optionally provide the parent span ID to add to the call event. This will automatically tie the call to a parent span in the UI."""
    tags: NotRequired[Nullable[Dict[str, str]]]
    r"""Optionally provide a list of tags to add to the call event. Useful for being able to understand aggregate analytics on some dimension."""
    configuration: NotRequired[Nullable[FunctionCallConfigurationTypedDict]]
    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 AppAPIPublicV2FunctionCallCallFunctionRequest(BaseModel):
    name: str
    r"""Provide a unique name of the task. A function with this name will be created in the project. Functions configuration is overridden by the request parameters."""

    instructions: OptionalNullable[str] = UNSET
    r"""Optionally provide an instruction for the model to complete the task. Recommended to be concise and to the point"""

    input_schema: OptionalNullable[Dict[str, Any]] = UNSET
    r"""Optionally provide an input schema for the task. 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"""Optionally provide an output schema for the task. Response is guaranteed to match the schema or throw an error. Can preferably include field descriptions to allow the model to reason about the output variables. 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."""

    input: OptionalNullable[Any] = UNSET
    r"""Optionally provide input data as context to complete the task. Could be a text, image, audio or a combination of these."""

    model: Optional[TModel] = None

    examples: OptionalNullable[List[Example]] = UNSET
    r"""Optionally provide examples of successful task completions. Will be added to the prompt to help the model understand the task from examples."""

    parent_span_id: OptionalNullable[str] = UNSET
    r"""Optionally provide the parent span ID to add to the call event. This will automatically tie the call to a parent span in the UI."""

    tags: OptionalNullable[Dict[str, str]] = UNSET
    r"""Optionally provide a list of tags to add to the call event. Useful for being able to understand aggregate analytics on some dimension."""

    configuration: OptionalNullable[FunctionCallConfiguration] = 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 = [
            "instructions",
            "input_schema",
            "output_schema",
            "input",
            "model",
            "examples",
            "parent_span_id",
            "tags",
            "configuration",
        ]
        nullable_fields = [
            "instructions",
            "input_schema",
            "output_schema",
            "input",
            "examples",
            "parent_span_id",
            "tags",
            "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
