"""Bounded Agent99 completion callback contracts.""" from __future__ import annotations from datetime import datetime from typing import Literal from pydantic import BaseModel, ConfigDict, Field class Agent99TelegramReceipt(BaseModel): model_config = ConfigDict(extra="forbid", str_strip_whitespace=True) sent: bool = False suppressed: bool = False reason: str | None = Field(default=None, max_length=80) message_format: str | None = Field(default=None, max_length=80) visual_sent: bool = False visual_file: str | None = Field( default=None, max_length=180, pattern=r"^[^/\\]+$", ) class Agent99ProblemReceipt(BaseModel): model_config = ConfigDict(extra="forbid") key: str | None = Field(default=None, max_length=240) occurrences: int = Field(default=0, ge=0) verified_resolved: int = Field(default=0, ge=0) failed: int = Field(default=0, ge=0) degraded: int = Field(default=0, ge=0) blocked: int = Field(default=0, ge=0) verifying: int = Field(default=0, ge=0) candidate_ready: int = Field(default=0, ge=0) class Agent99CompletionCallbackRequest(BaseModel): model_config = ConfigDict(extra="forbid", str_strip_whitespace=True) schema_version: Literal["agent99_completion_callback_v1"] callback_id: str = Field( min_length=3, max_length=180, pattern=r"^[A-Za-z0-9_.:-]+$" ) project_id: str = Field(default="awoooi", min_length=1, max_length=64) run_id: str = Field(min_length=3, max_length=180) trace_id: str = Field(min_length=3, max_length=180) work_item_id: str = Field(min_length=3, max_length=180) alert_id: str | None = Field(default=None, max_length=180) correlation_key: str | None = Field(default=None, max_length=240) source: str = Field(default="agent99", max_length=120) mode: str = Field(min_length=2, max_length=80) outcome_state: Literal[ "resolved", "candidate_ready", "verifying", "degraded", "blocked", "failed", ] controlled_apply: bool = False transport_ok: bool verifier_name: str = Field(min_length=2, max_length=160) verifier_passed: bool source_event_resolved: bool source_event_resolution_policy: str = Field(max_length=120) duration_seconds: float = Field(ge=0, le=3600) evidence_ref: str = Field(min_length=1, max_length=180, pattern=r"^[^/\\]+$") alert_kind: str | None = Field(default=None, max_length=120) alert_service: str | None = Field(default=None, max_length=160) alert_host: str | None = Field(default=None, max_length=160) telegram: Agent99TelegramReceipt = Field(default_factory=Agent99TelegramReceipt) problem: Agent99ProblemReceipt = Field(default_factory=Agent99ProblemReceipt) occurred_at: datetime class Agent99TelegramLifecycleRequest(BaseModel): """Bounded Agent99 event card handed to the canonical Telegram gateway.""" model_config = ConfigDict(extra="forbid", str_strip_whitespace=True) schema_version: Literal["agent99_telegram_lifecycle_v1"] delivery_id: str = Field( min_length=12, max_length=180, pattern=r"^[A-Za-z0-9_.:-]+$", ) project_id: Literal["awoooi"] = "awoooi" incident_id: str = Field( min_length=3, max_length=180, pattern=r"^[A-Za-z0-9_.:-]+$", ) fingerprint: str = Field(min_length=8, max_length=160) event_type: str = Field( min_length=2, max_length=96, pattern=r"^[A-Za-z0-9_.:-]+$", ) severity: Literal["info", "warning", "critical"] lifecycle: Literal[ "detected", "investigating", "remediating", "verifying", "recovered", "blocked", "unknown", ] state_key: str = Field(min_length=3, max_length=96) run_id: str | None = Field(default=None, max_length=180) title: str = Field(min_length=1, max_length=120) target: str = Field(min_length=1, max_length=120) impact: str = Field(min_length=1, max_length=300) action: str = Field(min_length=1, max_length=360) verification: str = Field(min_length=1, max_length=300) duration_text: str = Field(min_length=1, max_length=80) occurrences: int = Field(default=1, ge=1, le=1_000_000) next_update: str = Field(min_length=1, max_length=300) reply_to_message_id: int | None = Field(default=None, ge=1) occurred_at: datetime