File size: 1,693 Bytes
a15535e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
"""Pydantic action models for ForgeEnv (compatible with OpenEnv 0.2.x).

Episodes have two phases — drift_gen (Challenger) and repair (Solver) — so
we expose a single union ForgeAction that carries either a BreakageAction
or a RepairAction. The environment dispatches on which sub-field is set.
"""
from __future__ import annotations

from typing import Any, Literal, Optional

from pydantic import Field

from openenv.core import Action


class BreakageAction(Action):
    """Drift Generator's action: pick a primitive type + parameters."""

    action_type: Literal["breakage"] = "breakage"
    primitive_type: str = Field(
        ..., description="One of the registered breakage primitive class names"
    )
    params: dict[str, Any] = Field(
        default_factory=dict, description="Primitive-specific parameters"
    )


class RepairAction(Action):
    """Repair Agent's action: a unified diff (or full replacement script)."""

    action_type: Literal["repair"] = "repair"
    unified_diff: str = Field(..., description="Unified diff or full replacement script")


class ForgeAction(Action):
    """Union action: exactly one of `breakage` / `repair` must be set.

    This is the type registered with OpenEnv's `create_app`. It avoids
    Pydantic discriminated unions to keep the OpenAPI schema flat and
    cross-version-friendly.
    """

    breakage: Optional[BreakageAction] = None
    repair: Optional[RepairAction] = None

    def model_post_init(self, __context: Any) -> None:
        if (self.breakage is None) == (self.repair is None):
            raise ValueError(
                "ForgeAction requires exactly one of `breakage` or `repair` to be set."
            )