from enum import Enum from typing import Any from openenv.core.env_server.types import Action, Observation from pydantic import Field class ActionType(str, Enum): LABEL = "label" CLOSE_SPAM = "close_spam" REQUEST_INFO = "request_info" LINK_DUPLICATE = "link_duplicate" ASSIGN = "assign" COMMENT = "comment" MERGE_PR = "merge_pr" REJECT_PR = "reject_pr" REVIEW_PR_DIFF = "review_pr_diff" CHECK_DEPENDENCY = "check_dependency" FLAG_SECURITY = "flag_security" REVOKE_TRUST = "revoke_trust" QUERY_HISTORY = "query_history" REFLECT = "reflect" UPDATE_EPISODE = "update_episode" DELETE_EPISODE = "delete_episode" MERGE_EPISODES = "merge_episodes" WAIT = "wait" class SecurityVerdict(str, Enum): SAFE = "safe" SUSPICIOUS = "suspicious" MALICIOUS = "malicious" class OpsguardAction(Action): action_type: ActionType = Field(default=ActionType.WAIT) target_issue_id: int | None = Field(default=None, description="Issue/PR id from current observation") label: str | None = Field(default=None, description="Label name for LABEL action") duplicate_of_id: int | None = Field(default=None, description="Existing issue id this duplicates") assignee_login: str | None = Field(default=None, description="Maintainer login for ASSIGN") comment_body: str | None = Field(default=None, description="Body for COMMENT, REQUEST_INFO, REJECT_PR, FLAG_SECURITY") query: str | None = Field(default=None, description="Free-text query for QUERY_HISTORY") reasoning: str | None = Field(default=None, description="Optional rationale used by grader") security_verdict: SecurityVerdict | None = Field(default=None, description="Verdict for REVIEW_PR_DIFF / CHECK_DEPENDENCY") revoke_target_login: str | None = Field(default=None, description="Contributor to revoke trust from") class IssueView(Observation): issue_id: int = 0 number: int = 0 title: str = "" body: str = "" is_pr: bool = False pr_diff_preview: str = "" pr_changed_files: list[str] = Field(default_factory=list) pr_dependency_changes: list[dict[str, str]] = Field(default_factory=list) author_login: str = "" author_pr_count: int = 0 author_account_age_days: int = 0 author_first_contribution_days_ago: int = 0 available_labels: list[str] = Field(default_factory=list) comments_preview: list[dict[str, str]] = Field(default_factory=list) author_profile: dict[str, Any] = Field(default_factory=dict) behavior_tokens: list[str] = Field(default_factory=list) behavior_risk_score: float = 0.0 behavior_hints: list[str] = Field(default_factory=list) class OpsguardObservation(Observation): scenario_id: str = "" step: int = 0 step_budget: int = 0 queue_position: int = 0 queue_total: int = 0 current_issue: IssueView | None = None memory_hits: list[dict[str, Any]] = Field(default_factory=list) recent_actions: list[dict[str, Any]] = Field(default_factory=list) repo_health: float = 1.0 n_attacks_landed: int = 0 feedback: str = ""