File size: 1,406 Bytes
acf77ab
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
from __future__ import annotations

from typing import Literal

from pydantic import BaseModel, ConfigDict, Field

TerminationReason = Literal["target_hit", "max_iters", "stuck", "in_progress"]
IterationReason = Literal[
    "score_improved",
    "score_regressed",
    "score_plateau",
    "target_hit",
    "sandbox_error",
    "synthesizer_error",
]


class LoopConfig(BaseModel):
    model_config = ConfigDict(frozen=True)
    max_iters: int = Field(default=5, gt=0, le=100)
    target_score: float = Field(default=0.95, gt=0.0, le=2.0)
    tools: tuple[str, ...] = ("ruff", "imports")
    timeout_per_tool: float = 60.0
    top_k_citations: int = Field(default=5, gt=0, le=50)


class SynthesisResult(BaseModel):
    model_config = ConfigDict(frozen=True)
    proposed_files: dict[str, str]
    rationale: str
    cited_node_ids: tuple[str, ...]


class Iteration(BaseModel):
    model_config = ConfigDict(frozen=True)
    index: int
    cited_node_ids: tuple[str, ...]
    rationale: str
    proposed_files: dict[str, str]
    sandbox_score_before: float
    sandbox_score_after: float
    kept: bool
    reason: IterationReason


class RunResult(BaseModel):
    model_config = ConfigDict(frozen=True)
    run_id: str
    spec: str
    started_at: str
    ended_at: str
    final_score: float
    final_files: dict[str, str]
    iterations: tuple[Iteration, ...]
    terminated_by: TerminationReason