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

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

from ..._models import BaseModel

__all__ = [
    "LibraryScreenStartResponse",
    "Error",
    "Input",
    "InputProteins",
    "InputTarget",
    "InputTargetStructureTemplateTargetResponse",
    "InputTargetStructureTemplateTargetResponseChainSelection",
    "InputTargetStructureTemplateTargetResponseChainSelectionStructureTemplateTargetPolymerChainSpec",
    "InputTargetStructureTemplateTargetResponseChainSelectionStructureTemplateTargetLigandChainSpec",
    "InputTargetStructureTemplateTargetResponseStructure",
    "InputTargetNoTemplateTargetResponse",
    "InputTargetNoTemplateTargetResponseEntity",
    "InputTargetNoTemplateTargetResponseEntityProteinEntityResponse",
    "InputTargetNoTemplateTargetResponseEntityProteinEntityResponseModification",
    "InputTargetNoTemplateTargetResponseEntityProteinEntityResponseModificationCcdModificationResponse",
    "InputTargetNoTemplateTargetResponseEntityProteinEntityResponseModificationSmilesModificationResponse",
    "InputTargetNoTemplateTargetResponseEntityRnaEntityResponse",
    "InputTargetNoTemplateTargetResponseEntityRnaEntityResponseModification",
    "InputTargetNoTemplateTargetResponseEntityRnaEntityResponseModificationCcdModificationResponse",
    "InputTargetNoTemplateTargetResponseEntityRnaEntityResponseModificationSmilesModificationResponse",
    "InputTargetNoTemplateTargetResponseEntityDnaEntityResponse",
    "InputTargetNoTemplateTargetResponseEntityDnaEntityResponseModification",
    "InputTargetNoTemplateTargetResponseEntityDnaEntityResponseModificationCcdModificationResponse",
    "InputTargetNoTemplateTargetResponseEntityDnaEntityResponseModificationSmilesModificationResponse",
    "InputTargetNoTemplateTargetResponseEntityLigandCcdEntityResponse",
    "InputTargetNoTemplateTargetResponseEntityLigandSmilesEntityResponse",
    "InputTargetNoTemplateTargetResponseBond",
    "InputTargetNoTemplateTargetResponseBondAtom1",
    "InputTargetNoTemplateTargetResponseBondAtom1LigandAtomResponse",
    "InputTargetNoTemplateTargetResponseBondAtom1PolymerAtomResponse",
    "InputTargetNoTemplateTargetResponseBondAtom2",
    "InputTargetNoTemplateTargetResponseBondAtom2LigandAtomResponse",
    "InputTargetNoTemplateTargetResponseBondAtom2PolymerAtomResponse",
    "InputTargetNoTemplateTargetResponseConstraint",
    "InputTargetNoTemplateTargetResponseConstraintPocketConstraintResponse",
    "InputTargetNoTemplateTargetResponseConstraintContactConstraintResponse",
    "InputTargetNoTemplateTargetResponseConstraintContactConstraintResponseToken1",
    "InputTargetNoTemplateTargetResponseConstraintContactConstraintResponseToken1PolymerContactTokenResponse",
    "InputTargetNoTemplateTargetResponseConstraintContactConstraintResponseToken1LigandContactTokenResponse",
    "InputTargetNoTemplateTargetResponseConstraintContactConstraintResponseToken2",
    "InputTargetNoTemplateTargetResponseConstraintContactConstraintResponseToken2PolymerContactTokenResponse",
    "InputTargetNoTemplateTargetResponseConstraintContactConstraintResponseToken2LigandContactTokenResponse",
    "Progress",
]


class Error(BaseModel):
    code: str
    """Machine-readable error code"""

    message: str
    """Human-readable error message"""

    details: Optional[object] = None
    """Additional error details"""


class InputProteins(BaseModel):
    url: str
    """URL to download the file"""

    url_expires_at: datetime
    """When the presigned URL expires"""


class InputTargetStructureTemplateTargetResponseChainSelectionStructureTemplateTargetPolymerChainSpec(BaseModel):
    """
    Per-chain specification for a polymer (protein/RNA/DNA) chain in a structure template target.
    """

    chain_type: Literal["polymer"]

    crop_residues: Union[List[int], Literal["all"]]
    """
    0-indexed residue indices to retain from this chain, or 'all' to keep all
    residues. Residues not listed are excluded from the engine run.
    """

    epitope_residues: Optional[List[int]] = None
    """0-indexed residue indices where binder contact is desired (the epitope).

    All indices must be present in crop_residues.
    """

    flexible_residues: Optional[List[int]] = None
    """0-indexed residue indices allowed to move during design (e.g.

    flexible loop regions). All indices must be present in crop_residues.
    """


class InputTargetStructureTemplateTargetResponseChainSelectionStructureTemplateTargetLigandChainSpec(BaseModel):
    """Per-chain specification for a ligand chain in a structure template target.

    The full ligand is always included.
    """

    chain_type: Literal["ligand"]


InputTargetStructureTemplateTargetResponseChainSelection: TypeAlias = Union[
    InputTargetStructureTemplateTargetResponseChainSelectionStructureTemplateTargetPolymerChainSpec,
    InputTargetStructureTemplateTargetResponseChainSelectionStructureTemplateTargetLigandChainSpec,
]


class InputTargetStructureTemplateTargetResponseStructure(BaseModel):
    url: str
    """URL to download the file"""

    url_expires_at: datetime
    """When the presigned URL expires"""


class InputTargetStructureTemplateTargetResponse(BaseModel):
    """Target defined by an uploaded 3D structure (CIF or PDB file).

    Only chains included in chain_selection are used.
    """

    chain_selection: Dict[str, InputTargetStructureTemplateTargetResponseChainSelection]
    """Chains selected from the uploaded structure, keyed by chain ID.

    Only chains listed here are included in the engine run — any chains omitted from
    this mapping are ignored. Each value defines which residues to keep, which are
    epitope residues, and which are flexible.
    """

    structure: InputTargetStructureTemplateTargetResponseStructure

    type: Literal["structure_template"]


class InputTargetNoTemplateTargetResponseEntityProteinEntityResponseModificationCcdModificationResponse(BaseModel):
    residue_index: int
    """0-based index of the residue to modify"""

    type: Literal["ccd"]

    value: str
    """CCD code from RCSB PDB (e.g.

    'MSE' for selenomethionine, 'SEP' for phosphoserine)
    """


class InputTargetNoTemplateTargetResponseEntityProteinEntityResponseModificationSmilesModificationResponse(BaseModel):
    residue_index: int
    """0-based index of the residue to modify"""

    type: Literal["smiles"]

    value: str
    """SMILES string for the modification"""


InputTargetNoTemplateTargetResponseEntityProteinEntityResponseModification: TypeAlias = Union[
    InputTargetNoTemplateTargetResponseEntityProteinEntityResponseModificationCcdModificationResponse,
    InputTargetNoTemplateTargetResponseEntityProteinEntityResponseModificationSmilesModificationResponse,
]


class InputTargetNoTemplateTargetResponseEntityProteinEntityResponse(BaseModel):
    chain_ids: List[str]
    """Chain IDs for this entity"""

    modifications: List[InputTargetNoTemplateTargetResponseEntityProteinEntityResponseModification]
    """Post-translational modifications"""

    type: Literal["protein"]

    value: str
    """Amino acid sequence (one-letter codes)"""

    cyclic: Optional[bool] = None
    """Whether the sequence is cyclic"""


class InputTargetNoTemplateTargetResponseEntityRnaEntityResponseModificationCcdModificationResponse(BaseModel):
    residue_index: int
    """0-based index of the residue to modify"""

    type: Literal["ccd"]

    value: str
    """CCD code from RCSB PDB (e.g.

    'MSE' for selenomethionine, 'SEP' for phosphoserine)
    """


class InputTargetNoTemplateTargetResponseEntityRnaEntityResponseModificationSmilesModificationResponse(BaseModel):
    residue_index: int
    """0-based index of the residue to modify"""

    type: Literal["smiles"]

    value: str
    """SMILES string for the modification"""


InputTargetNoTemplateTargetResponseEntityRnaEntityResponseModification: TypeAlias = Union[
    InputTargetNoTemplateTargetResponseEntityRnaEntityResponseModificationCcdModificationResponse,
    InputTargetNoTemplateTargetResponseEntityRnaEntityResponseModificationSmilesModificationResponse,
]


class InputTargetNoTemplateTargetResponseEntityRnaEntityResponse(BaseModel):
    chain_ids: List[str]
    """Chain IDs for this entity"""

    modifications: List[InputTargetNoTemplateTargetResponseEntityRnaEntityResponseModification]
    """Chemical modifications"""

    type: Literal["rna"]

    value: str
    """RNA nucleotide sequence (A, C, G, U, N)"""

    cyclic: Optional[bool] = None
    """Whether the sequence is cyclic"""


class InputTargetNoTemplateTargetResponseEntityDnaEntityResponseModificationCcdModificationResponse(BaseModel):
    residue_index: int
    """0-based index of the residue to modify"""

    type: Literal["ccd"]

    value: str
    """CCD code from RCSB PDB (e.g.

    'MSE' for selenomethionine, 'SEP' for phosphoserine)
    """


class InputTargetNoTemplateTargetResponseEntityDnaEntityResponseModificationSmilesModificationResponse(BaseModel):
    residue_index: int
    """0-based index of the residue to modify"""

    type: Literal["smiles"]

    value: str
    """SMILES string for the modification"""


InputTargetNoTemplateTargetResponseEntityDnaEntityResponseModification: TypeAlias = Union[
    InputTargetNoTemplateTargetResponseEntityDnaEntityResponseModificationCcdModificationResponse,
    InputTargetNoTemplateTargetResponseEntityDnaEntityResponseModificationSmilesModificationResponse,
]


class InputTargetNoTemplateTargetResponseEntityDnaEntityResponse(BaseModel):
    chain_ids: List[str]
    """Chain IDs for this entity"""

    modifications: List[InputTargetNoTemplateTargetResponseEntityDnaEntityResponseModification]
    """Chemical modifications"""

    type: Literal["dna"]

    value: str
    """DNA nucleotide sequence (A, C, G, T, N)"""

    cyclic: Optional[bool] = None
    """Whether the sequence is cyclic"""


class InputTargetNoTemplateTargetResponseEntityLigandCcdEntityResponse(BaseModel):
    chain_ids: List[str]
    """Chain IDs for this ligand"""

    type: Literal["ligand_ccd"]

    value: str
    """CCD code (e.g., ATP, ADP)"""


class InputTargetNoTemplateTargetResponseEntityLigandSmilesEntityResponse(BaseModel):
    chain_ids: List[str]
    """Chain IDs for this ligand"""

    type: Literal["ligand_smiles"]

    value: str
    """SMILES string representing the ligand"""


InputTargetNoTemplateTargetResponseEntity: TypeAlias = Union[
    InputTargetNoTemplateTargetResponseEntityProteinEntityResponse,
    InputTargetNoTemplateTargetResponseEntityRnaEntityResponse,
    InputTargetNoTemplateTargetResponseEntityDnaEntityResponse,
    InputTargetNoTemplateTargetResponseEntityLigandCcdEntityResponse,
    InputTargetNoTemplateTargetResponseEntityLigandSmilesEntityResponse,
]


class InputTargetNoTemplateTargetResponseBondAtom1LigandAtomResponse(BaseModel):
    atom_name: str
    """Standardized atom name (verifiable in CIF file on RCSB)"""

    chain_id: str
    """Chain ID containing the atom"""

    type: Literal["ligand_atom"]


class InputTargetNoTemplateTargetResponseBondAtom1PolymerAtomResponse(BaseModel):
    atom_name: str
    """Standardized atom name (verifiable in CIF file on RCSB)"""

    chain_id: str
    """Chain ID containing the atom"""

    residue_index: int
    """0-based residue index"""

    type: Literal["polymer_atom"]


InputTargetNoTemplateTargetResponseBondAtom1: TypeAlias = Union[
    InputTargetNoTemplateTargetResponseBondAtom1LigandAtomResponse,
    InputTargetNoTemplateTargetResponseBondAtom1PolymerAtomResponse,
]


class InputTargetNoTemplateTargetResponseBondAtom2LigandAtomResponse(BaseModel):
    atom_name: str
    """Standardized atom name (verifiable in CIF file on RCSB)"""

    chain_id: str
    """Chain ID containing the atom"""

    type: Literal["ligand_atom"]


class InputTargetNoTemplateTargetResponseBondAtom2PolymerAtomResponse(BaseModel):
    atom_name: str
    """Standardized atom name (verifiable in CIF file on RCSB)"""

    chain_id: str
    """Chain ID containing the atom"""

    residue_index: int
    """0-based residue index"""

    type: Literal["polymer_atom"]


InputTargetNoTemplateTargetResponseBondAtom2: TypeAlias = Union[
    InputTargetNoTemplateTargetResponseBondAtom2LigandAtomResponse,
    InputTargetNoTemplateTargetResponseBondAtom2PolymerAtomResponse,
]


class InputTargetNoTemplateTargetResponseBond(BaseModel):
    atom1: InputTargetNoTemplateTargetResponseBondAtom1

    atom2: InputTargetNoTemplateTargetResponseBondAtom2


class InputTargetNoTemplateTargetResponseConstraintPocketConstraintResponse(BaseModel):
    """Constrains the binder to interact with specific pocket residues on the target."""

    binder_chain_id: str
    """Chain ID of the binder molecule"""

    contact_residues: Dict[str, List[int]]
    """Binding pocket residues keyed by chain ID.

    Each key is a chain ID (e.g. "A") and the value is an array of 0-indexed residue
    indices that define the pocket on that chain.
    """

    max_distance_angstrom: float
    """Maximum allowed distance in Angstroms between binder and pocket residues.

    Typical range: 4-8 A.
    """

    type: Literal["pocket"]

    force: Optional[bool] = None
    """Whether to force the constraint"""


class InputTargetNoTemplateTargetResponseConstraintContactConstraintResponseToken1PolymerContactTokenResponse(
    BaseModel
):
    chain_id: str
    """Chain ID"""

    residue_index: int
    """0-based residue index"""

    type: Literal["polymer_contact"]


class InputTargetNoTemplateTargetResponseConstraintContactConstraintResponseToken1LigandContactTokenResponse(BaseModel):
    atom_name: str
    """Atom name"""

    chain_id: str
    """Chain ID"""

    type: Literal["ligand_contact"]


InputTargetNoTemplateTargetResponseConstraintContactConstraintResponseToken1: TypeAlias = Union[
    InputTargetNoTemplateTargetResponseConstraintContactConstraintResponseToken1PolymerContactTokenResponse,
    InputTargetNoTemplateTargetResponseConstraintContactConstraintResponseToken1LigandContactTokenResponse,
]


class InputTargetNoTemplateTargetResponseConstraintContactConstraintResponseToken2PolymerContactTokenResponse(
    BaseModel
):
    chain_id: str
    """Chain ID"""

    residue_index: int
    """0-based residue index"""

    type: Literal["polymer_contact"]


class InputTargetNoTemplateTargetResponseConstraintContactConstraintResponseToken2LigandContactTokenResponse(BaseModel):
    atom_name: str
    """Atom name"""

    chain_id: str
    """Chain ID"""

    type: Literal["ligand_contact"]


InputTargetNoTemplateTargetResponseConstraintContactConstraintResponseToken2: TypeAlias = Union[
    InputTargetNoTemplateTargetResponseConstraintContactConstraintResponseToken2PolymerContactTokenResponse,
    InputTargetNoTemplateTargetResponseConstraintContactConstraintResponseToken2LigandContactTokenResponse,
]


class InputTargetNoTemplateTargetResponseConstraintContactConstraintResponse(BaseModel):
    max_distance_angstrom: float
    """Maximum distance in Angstroms"""

    token1: InputTargetNoTemplateTargetResponseConstraintContactConstraintResponseToken1

    token2: InputTargetNoTemplateTargetResponseConstraintContactConstraintResponseToken2

    type: Literal["contact"]

    force: Optional[bool] = None
    """Whether to force the constraint"""


InputTargetNoTemplateTargetResponseConstraint: TypeAlias = Union[
    InputTargetNoTemplateTargetResponseConstraintPocketConstraintResponse,
    InputTargetNoTemplateTargetResponseConstraintContactConstraintResponse,
]


class InputTargetNoTemplateTargetResponse(BaseModel):
    """Target defined by sequences only, without a 3D structure template"""

    entities: List[InputTargetNoTemplateTargetResponseEntity]
    """Entities (proteins, RNA, DNA, ligands) defining the target complex."""

    type: Literal["no_template"]

    bonds: Optional[List[InputTargetNoTemplateTargetResponseBond]] = None
    """Covalent bond constraints between atoms in the target complex."""

    constraints: Optional[List[InputTargetNoTemplateTargetResponseConstraint]] = None
    """Structural constraints (pocket and contact)"""

    epitope_residues: Optional[Dict[str, List[int]]] = None
    """Residues where binder contact is desired (the epitope).

    Each key is a chain ID and the value is an array of 0-indexed residue indices.
    All indices must be valid within the corresponding entity sequence.
    """


InputTarget: TypeAlias = Union[InputTargetStructureTemplateTargetResponse, InputTargetNoTemplateTargetResponse]


class Input(BaseModel):
    proteins: InputProteins

    target: InputTarget
    """Target specification (structure template or template-free)"""


class Progress(BaseModel):
    num_proteins_failed: int
    """Number of accepted proteins that reached terminal failure during screening."""

    num_proteins_screened: int
    """Number of accepted proteins that produced usable screening results."""

    total_proteins_to_screen: int
    """Total number of proteins accepted into the screening run."""

    latest_result_id: Optional[str] = None
    """ID of the latest result"""


class LibraryScreenStartResponse(BaseModel):
    """A protein library screening engine run"""

    id: str
    """Unique ProteinLibraryScreen identifier"""

    completed_at: Optional[datetime] = None

    created_at: datetime

    data_deleted_at: Optional[datetime] = None
    """When the input, output, and result data was permanently deleted.

    Null if data has not been deleted.
    """

    engine: Literal["boltz-protein-screen"]
    """Engine used for protein library screen"""

    engine_version: str
    """Engine version used for protein library screen"""

    error: Optional[Error] = None

    input: Input

    livemode: bool
    """Whether this resource was created with a live API key."""

    progress: Optional[Progress] = None

    started_at: Optional[datetime] = None

    status: Literal["pending", "running", "succeeded", "failed", "stopped"]

    stopped_at: Optional[datetime] = None

    workspace_id: str
    """Workspace ID"""

    idempotency_key: Optional[str] = None
    """Client-provided idempotency key"""
