File size: 3,550 Bytes
dbf5e96
b2b578f
dbf5e96
b2b578f
 
dbf5e96
b2b578f
 
 
 
 
 
 
 
 
dbf5e96
 
b2b578f
dbf5e96
 
 
 
 
 
b2b578f
dbf5e96
 
b2b578f
 
dbf5e96
b2b578f
 
dbf5e96
b2b578f
 
dbf5e96
b2b578f
 
dbf5e96
 
 
b2b578f
 
 
dbf5e96
 
b2b578f
dbf5e96
 
b2b578f
 
dbf5e96
b2b578f
 
 
 
dbf5e96
b2b578f
 
dbf5e96
b2b578f
 
 
 
 
 
 
 
dbf5e96
 
 
 
 
 
b2b578f
dbf5e96
74c9d03
 
 
 
 
dbf5e96
74c9d03
 
b2b578f
74c9d03
b2b578f
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
"""
CodeReviewEnv β€” OpenEnv MCP-compliant typed models.

Follows the same MCP tool-calling pattern as the reference environments
(calendar_env, repl_env). Agents interact via tool calls:

  ListToolsAction  β€” discover available tools
  ToolCallAction   β€” call a tool by name with arguments

Available tools:
  get_code       β€” get the buggy code snippet for review
  analyze_code   β€” get structural analysis of the code
  check_line     β€” check if a specific line contains a bug (+/- reward)
  get_hint       β€” get a progressive hint (costs efficiency)
  submit_review  β€” submit final structured review (ends episode)
"""

from typing import Any, Dict, List, Literal, Optional

from pydantic import ConfigDict, Field

from openenv.core.env_server.types import Action, Observation, State


# ─── MCP Action (matches calendar_env pattern) ──────────────────────────────


class MCPAction(Action):
    """MCP tool-calling action. Agents either list tools or call a tool."""

    action_type: Literal["ListToolsAction", "ToolCallAction"] = Field(
        ..., description="Type of action to perform"
    )
    tool_name: Optional[str] = Field(
        None, description="Name of tool to call (required for ToolCallAction)"
    )
    arguments: Optional[Dict[str, Any]] = Field(
        default_factory=dict, description="Arguments for the tool"
    )


class CodeReviewAction(MCPAction):
    """Code review action β€” inherits MCP tool-calling interface."""
    pass


# ─── MCP Observation (matches calendar_env pattern) ─────────────────────────


class MCPObservation(Observation):
    """MCP observation returned after tool calls."""

    success: bool = Field(True, description="Whether the action succeeded")
    error_message: Optional[str] = Field(None, description="Error details if failed")
    tools_list: Optional[List[Dict[str, Any]]] = Field(
        None, description="Available tools (for ListToolsAction)"
    )
    tool_result: Optional[Dict[str, Any]] = Field(
        None, description="Result from tool call"
    )
    metadata: Dict[str, Any] = Field(default_factory=dict)
    done: bool = Field(False, description="Whether the episode is over")
    reward: Optional[float] = Field(None, description="Reward signal")


class CodeReviewObservation(MCPObservation):
    """Code review observation β€” inherits MCP observation."""
    pass


# ─── State ───────────────────────────────────────────────────────────────────


class CodeReviewState(State):
    """Full environment state β€” includes gold answers (hidden from agent)."""

    original_code: str = Field(default="", description="Clean code before injection")
    buggy_code: str = Field(default="", description="Code with injected bugs")
    gold_bugs: List[Dict[str, Any]] = Field(
        default_factory=list,
        description="Injected bugs: [{description, lines, fix, bug_type}, ...]",
    )
    language: str = Field(default="python", description="Source language")
    difficulty: str = Field(default="easy", description="Difficulty tier")
    hint_count: int = Field(default=0, description="Hints requested")
    snippet_name: str = Field(default="", description="Which snippet was used")
    flagged_lines: List[int] = Field(default_factory=list, description="Lines flagged so far")