# This file was auto-generated by Fern from our API Definition.

import typing

import pydantic
from ..core.pydantic_utilities import IS_PYDANTIC_V2
from ..core.unchecked_base_model import UncheckedBaseModel
from .score_field import ScoreField
from .template_variable import TemplateVariable


class AgentScorer(UncheckedBaseModel):
    """
    Agent-based scorer using ephemeral agents.

    Uses Scout's ephemeral agent system to evaluate outputs. The agent can
    reason about the evaluation, use tools, and return a composite score with
    dimensional breakdown.

    IMPORTANT: The prompt_template should contain ONLY evaluation instructions.
    DO NOT include JSON schema definitions - they are automatically generated
    from the 'criteria' field. The system enforces this output structure:
    {
        "score": 0.82,          // Composite score (0-1)
        "dimensions": {         // Scores for each criterion
            "helpfulness": 0.9,
            "accuracy": 0.7
        },
        "reasoning": "..."      // Explanation of scores
    }

    Example (CORRECT - simple evaluation):
        scorer = AgentScorer(
            id="quality_agent",
            name="Response Quality",
            type="agent",
            prompt_template='''Evaluate the response quality.

            Question: {{input}}
            Answer: {{output}}
            Expected: {{expected}}

            Consider helpfulness and accuracy in your evaluation.''',
            model="claude-sonnet-4",
            criteria=["helpfulness", "accuracy"]  # Defines JSON dimensions
        )

    Example (CORRECT - with tools):
        scorer = AgentScorer(
            id="factual_accuracy",
            name="Factual Accuracy Agent",
            type="agent",
            prompt_template='''Check if the output is factually accurate.
            Query the knowledge base if needed to verify claims.

            Output to verify: {{output}}''',
            model="claude-sonnet-4",
            criteria=["accuracy", "grounded"],
            tools=["scout_table_tools", "scout_document_tools"]
        )

    Example (WRONG - don't do this):
        scorer = AgentScorer(
            ...
            prompt_template='''Evaluate...

            Return JSON: {"score": 0.9, "reasoning": "..."}''',  # ❌ NO!
            ...
        )
    """

    type: typing.Literal["agent"] = "agent"
    id: str = pydantic.Field()
    """
    Unique scorer identifier
    """

    name: str = pydantic.Field()
    """
    Human-readable scorer name
    """

    description: str = pydantic.Field()
    """
    What this scorer evaluates
    """

    pass_threshold: typing.Optional[float] = pydantic.Field(default=None)
    """
    Optional pass/fail threshold (0-1)
    """

    tags: typing.Optional[typing.List[str]] = pydantic.Field(default=None)
    """
    Categorization tags
    """

    prompt_template: str = pydantic.Field()
    """
    Prompt template with {input}, {output}, {expected} placeholders
    """

    model: typing.Optional[str] = pydantic.Field(default=None)
    """
    Model to use for agent
    """

    criteria: typing.Optional[typing.List[str]] = pydantic.Field(default=None)
    """
    [DEPRECATED] Use score_fields instead. List of criterion names.
    """

    dimension_weights: typing.Optional[typing.Dict[str, typing.Optional[float]]] = pydantic.Field(default=None)
    """
    [DEPRECATED] Use score_fields with weight property instead.
    """

    score_fields: typing.Optional[typing.List[ScoreField]] = pydantic.Field(default=None)
    """
    Rich scoring dimension configurations with min/max/weight/description
    """

    tools: typing.Optional[typing.List[str]] = pydantic.Field(default=None)
    """
    Scout tools agent can use (e.g., ['scout_table_tools'])
    """

    variables: typing.Optional[typing.List[TemplateVariable]] = pydantic.Field(default=None)
    """
    Declared template variables. At execution time, validates that required variables are present in context.
    """

    if IS_PYDANTIC_V2:
        model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True)  # type: ignore # Pydantic v2
    else:

        class Config:
            frozen = True
            smart_union = True
            extra = pydantic.Extra.allow
