# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.

from __future__ import annotations

from typing import Dict, List, Union, Optional
from typing_extensions import Literal, TypeAlias

from .._models import BaseModel
from .workflow_item import WorkflowItem

__all__ = [
    "PlanConfigOutput",
    "Plan",
    "PlanBranchConfigOutput",
    "PlanBranchConfigOutputConditionalWorkflow",
    "PlanLoopConfigOutput",
    "PlanLoopConfigOutputLoopInputs",
    "PlanLoopConfigOutputLoopInputsSelfEdge",
    "Workflows",
    "WorkflowsWorkflowOutput",
]


class PlanBranchConfigOutputConditionalWorkflow(BaseModel):
    """
    Representation of a workflow that is part of a branch complex
    Attributes:
        condition: Either if, elif, or else
        condition_input_var: the variable that is inputted into the unary condition
        operator: the unary condition operator
        reference_var: the unary condition reference variable that is used to build a predicate function with the operator
        condition_tree: a compound logical expression expressed as a tree (see CompoundCondition), optional if the above condition vars are set
        workflow_nodes: to be set to a list of all nodes in the workflow at runtime, so they can
                        be easily ignored if this branch is not selected to run
    """

    condition: Literal["if", "elif", "else"]
    """The condition type"""

    workflow_name: str
    """The name of the abstract workflow"""

    condition_input_var: Optional[str] = None
    """The input variable to the unary condition"""

    condition_tree: Optional["CompoundConditionOutput"] = None
    """Representation of a compound boolean statement, i.e.

    a negation, conjunction, or disjunction of UnaryConditions
    """

    operator: Optional[str] = None
    """The operator to use in the unary condition"""

    reference_var: Optional[str] = None
    """The reference variable to use in the unary condition"""

    workflow_alias: Optional[str] = None
    """The alias of the abstract workflow in the graph"""

    workflow_inputs: Optional[Dict[str, Union[str, Dict[str, Union[str, object]]]]] = None
    """The inputs to the workflow"""

    workflow_nodes: Optional[List[str]] = None
    """The nodes that make up the workflow"""


class PlanBranchConfigOutput(BaseModel):
    """
    A representation of a branch complex.
    Branches can have multiple conditional workflows, each with a condition and a workflow.
    They need not end with an else branch, but if they don't then the user must provide a
    default source to pass through the merge node from outside the branch.
    Attributes:
        branch: name of the branch
        conditional_workflows: conditional workflows associated with the branch
        merge_outputs: Map where each key is an alias mapping to a list of node outputs the conditional workflows.
                       For example, the config:
                           - branch: do_A_or_B
                             ...
                             merge_outputs:
                                 response_A_or_B:
                                 - "workflow_A.response_node.output"
                                 - "workflow_B.response_node.output"
                                 chunks_A_or_B:
                                 - "workflow_A.chunks_node.output"
                                 - "workflow_B.chunks_node.output"
                        allows the user to reference the response/chunks outputs of either branch via the aliases
                        "do_A_or_B.response_A_or_B.output" and "do_A_or_B.chunks_A_or_B.output" in downstream steps of a plan
    """

    branch: str

    conditional_workflows: List[PlanBranchConfigOutputConditionalWorkflow]

    merge_outputs: Optional[Dict[str, List[str]]] = None

    save_merge_to_memory: Optional[Dict[str, str]] = None


class PlanLoopConfigOutputLoopInputsSelfEdge(BaseModel):
    """
    A self edge in a loop complex is configured with 2 attributes:
        (a) node_name: the name of a node within the loop whose output will be passed to the next iteration,
        (b) a default value or source to use when the loop is at its first iteration
    """

    node_name: str

    default_source: Optional[str] = None

    default_value: Optional[object] = None


PlanLoopConfigOutputLoopInputs: TypeAlias = Union[str, PlanLoopConfigOutputLoopInputsSelfEdge]


class PlanLoopConfigOutput(BaseModel):
    """
    A representation of a loop complex
    Currently, loops are implemented as a series of BranchConfigs.

    Attributes:
        name: name of the loop
        workflow: the workflow to be repeated in the loop
        condition: the condition that yields True if the loop is to be continued
        max_iter: the maximum number of iterations the loop will run. required for now.
        loop_inputs: a mapping of inputs to the looped workflow to either a string or SelfEdge.
                     If a string, the key is assumed to map to a raw input to the plan or another
                     container's (branch/workflow) node's output.
                     If a SelfEdge, the key is assumed to map to a node within the loop whose output
                     will be passed to the next iteration.
        merge_outputs: a map to define the final outputs of the loop.
                       The key is an alias that maps to a node within the workflow.
    """

    condition: "CompoundConditionOutput"
    """Representation of a compound boolean statement, i.e.

    a negation, conjunction, or disjunction of UnaryConditions
    """

    max_iter: int

    name: str

    workflow: WorkflowItem
    """
    Representation of an instance of an abstract Workflow Attributes: workflow_name:
    Key in the map of workflows defined at the top of a plan config workflow_alias:
    Alias of the abstract workflow in the graph. If None, defaults to workflow_name.
    Use in order to re-use the same abstract workflow in multiple portions of the
    graph. workflow_inputs: Inputs to the workflow can be: 1) empty if this workflow
    does not receive input from another workflow, 2) a dictionary mapping another
    workflow's outputs or a branch's merged outputs to this workflows input keys For
    case 2, inputs can be a mapping from: a) str to str b) str to dict(str, str) c)
    str to dict(str, dict(str, str))
    """

    loop_inputs: Optional[Dict[str, PlanLoopConfigOutputLoopInputs]] = None

    merge_outputs: Optional[Dict[str, str]] = None


Plan: TypeAlias = Union[WorkflowItem, PlanBranchConfigOutput, PlanLoopConfigOutput]


class WorkflowsWorkflowOutput(BaseModel):
    """
    A representation of a DAG of functions
    Attributes:
        name: name of the workflow
        nodes: a list of node items that make up the workflow
    """

    name: str

    nodes: List["NodeItemOutput"]


Workflows: TypeAlias = Union[WorkflowsWorkflowOutput, str, List["NodeItemOutput"]]


class PlanConfigOutput(BaseModel):
    """Representation of a plan, i.e. a composition of workflows and branch complexes

    Public attributes:
        workflows: maps a workflow "name" to either a workflow yaml file or an inline workflow definition
        plan: representation of the graph connecting workflows / branch complexes

    Private attributes:
        helper_workflows: a list of workflows created by default, in order to
                          support loops and other control flow features
    """

    plan: List[Plan]

    id: Optional[str] = None

    account_id: Optional[str] = None

    application_variant_id: Optional[str] = None

    base_url: Optional[str] = None

    concurrency_default: Optional[bool] = None

    datasets: Optional[List[object]] = None

    egp_api_key_override: Optional[str] = None

    egp_ui_evaluation: Optional[object] = None

    evaluations: Optional[List["NodeItemOutput"]] = None

    final_output_nodes: Optional[List[str]] = None

    nodes_to_log: Union[str, List[str], None] = None

    num_workers: Optional[int] = None

    streaming_nodes: Optional[List[str]] = None

    subtype: Optional[Literal["chat", "report"]] = None

    type: Optional[Literal["workflow", "plan", "state_machine"]] = None

    user_input: Optional[object] = None

    workflows: Optional[Dict[str, Workflows]] = None


from .node_item_output import NodeItemOutput
from .compound_condition_output import CompoundConditionOutput
