Spaces:
No application file
No application file
| # models.py – Typed Models (Discriminated Unions, POMDP Separation) | |
| from typing import Literal, Union, Annotated, Optional | |
| from dataclasses import dataclass | |
| from pydantic import BaseModel, Field, TypeAdapter, field_validator | |
| # ---------------------------------------------------------------------- | |
| # Action classes (discriminated union) | |
| # ---------------------------------------------------------------------- | |
| class Action(BaseModel): | |
| action_type: Literal["write_comment", "skip", "done", "ask_question", | |
| "propose_fix", "execute", "inspect", "run_linter", | |
| "run_tests", "query_docs"] | |
| class WriteComment(Action): | |
| action_type: Literal["write_comment"] = "write_comment" | |
| comment_text: str = Field(..., min_length=1) | |
| class Skip(Action): | |
| action_type: Literal["skip"] = "skip" | |
| class Done(Action): | |
| action_type: Literal["done"] = "done" | |
| class AskQuestion(Action): | |
| action_type: Literal["ask_question"] = "ask_question" | |
| question: str = Field(..., min_length=1) | |
| class ProposeFix(Action): | |
| action_type: Literal["propose_fix"] = "propose_fix" | |
| fix_code: str = Field(..., min_length=1) | |
| def not_empty(cls, v: str) -> str: | |
| if not v.strip(): | |
| raise ValueError('fix_code cannot be empty') | |
| return v | |
| class Execute(Action): | |
| action_type: Literal["execute"] = "execute" | |
| class Inspect(Action): | |
| action_type: Literal["inspect"] = "inspect" | |
| class RunLinter(Action): | |
| action_type: Literal["run_linter"] = "run_linter" | |
| class RunTests(Action): | |
| action_type: Literal["run_tests"] = "run_tests" | |
| class QueryDocs(Action): | |
| action_type: Literal["query_docs"] = "query_docs" | |
| query_topic: str = Field(..., min_length=1) | |
| # Discriminated union for one‑line polymorphic deserialization | |
| AnyAction = Annotated[ | |
| Union[WriteComment, Skip, Done, AskQuestion, ProposeFix, | |
| Execute, Inspect, RunLinter, RunTests, QueryDocs], | |
| Field(discriminator='action_type') | |
| ] | |
| action_adapter = TypeAdapter(AnyAction) | |
| # ---------------------------------------------------------------------- | |
| # Observation (POMDP – what the agent sees) | |
| # ---------------------------------------------------------------------- | |
| class Observation: | |
| code_snippet: str | |
| last_tool_output: str = "" | |
| step: int = 0 | |
| done: bool = False | |
| # ---------------------------------------------------------------------- | |
| # Reward (lightweight) | |
| # ---------------------------------------------------------------------- | |
| class Reward: | |
| value: float | |
| # ---------------------------------------------------------------------- | |
| # State (full environment state – not exposed to agent) | |
| # ---------------------------------------------------------------------- | |
| class State: | |
| pr_title: str | |
| pr_description: str | |
| code_snippet: str | |
| comments: list[str] | |
| test_results: Optional[str] | |
| step: int | |
| done: bool |