Coder preparations
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
# orchestrator/run_context.py
|
||||
from __future__ import annotations
|
||||
|
||||
import secrets
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime, timezone
|
||||
from typing import Any
|
||||
|
||||
from agents.coders.state import AgentState
|
||||
from common.gitea_mcp_client import GiteaMCPClient
|
||||
from common.llm_client import LLMClient
|
||||
from common.time import now_iso, now_iso_plus
|
||||
from common.youtrack_mcp_client import YouTrackMCPClient
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class AgentConfig:
|
||||
# ── project-level ──────────────────────────────────────────
|
||||
youtrack_project: str
|
||||
gitea_repo: str
|
||||
gitea_target_branch: str = "main"
|
||||
|
||||
# ── limits (snapshotted into state at run start) ───────────
|
||||
max_plan_attempts: int = 3
|
||||
max_act_attempts: int = 5
|
||||
max_ci_self_resolve_attempts: int = 2
|
||||
max_clarification_rounds: int = 3
|
||||
max_rework_rounds: int = 2
|
||||
wall_clock_minutes: int = 60
|
||||
token_budget: int = 500_000
|
||||
|
||||
# ── human-await timers ─────────────────────────────────────
|
||||
re_ping_after_days: int = 3
|
||||
abandon_after_days: int = 5
|
||||
|
||||
# ── reviewer policy ────────────────────────────────────────
|
||||
reviewer_fallback: str = "codeowners" # codeowners | blame | on_call
|
||||
|
||||
# ── language hints (for Plan) ──────────────────────────────
|
||||
language_markers: dict[str, list[str]] = None # filled from project
|
||||
|
||||
|
||||
@dataclass
|
||||
class RunContext:
|
||||
"""
|
||||
Everything a handler needs to do its job: the ports it talks to, the
|
||||
persisted state for this issue, and the identifiers it must stamp into
|
||||
comments and state.
|
||||
"""
|
||||
# ── identifiers ────────────────────────────────────────────
|
||||
agent_id: str
|
||||
issue_id: str
|
||||
run_id: str # one logical attempt; stable across calls
|
||||
attempt: int # retry counter within the run
|
||||
|
||||
# ── ports (outbound systems) ───────────────────────────────
|
||||
llm: LLMClient
|
||||
youtrack: YouTrackMCPClient
|
||||
gitea: GiteaMCPClient
|
||||
|
||||
# ── persisted pipeline state for this issue ────────────────
|
||||
state: AgentState
|
||||
|
||||
# ── static config for this run ─────────────────────────────
|
||||
config: AgentConfig
|
||||
|
||||
# ── convenience (thin, no hidden behavior) ─────────────────
|
||||
|
||||
def now(self) -> str:
|
||||
return now_iso()
|
||||
|
||||
def now_plus(self, **delta) -> str:
|
||||
return now_iso_plus(**delta)
|
||||
|
||||
|
||||
def new_run_id() -> str:
|
||||
"""
|
||||
Generate a run id: one logical attempt at a task.
|
||||
|
||||
Format: run-YYYYMMDD-HHMMSS-<6 hex chars>
|
||||
Example: run-20260921-114500-a3f1c2
|
||||
|
||||
- Timestamp prefix makes ids sortable and human-readable in logs.
|
||||
- Random suffix prevents collisions when two runs start in the same
|
||||
second (e.g., parallel issues, fast retries, tests).
|
||||
- The "run-" prefix makes it obvious what kind of id this is when it
|
||||
appears next to a comment marker or in a state file.
|
||||
"""
|
||||
ts = datetime.now(timezone.utc).strftime("%Y%m%d-%H%M%S")
|
||||
suffix = secrets.token_hex(3) # 3 bytes -> 6 hex chars
|
||||
return f"run-{ts}-{suffix}"
|
||||
Reference in New Issue
Block a user