Kairo-Jinkendo/backend/steering/agent_slots/review_due.py

55 lines
1.8 KiB
Python
Raw Permalink Normal View History

"""Agent slots for due planned reviews."""
from __future__ import annotations
from datetime import datetime, timezone
from typing import Any
from steering.eval_context import SteeringEvalContext
def _parse_due(value: Any) -> datetime | None:
if not value:
return None
if isinstance(value, datetime):
return value if value.tzinfo else value.replace(tzinfo=timezone.utc)
try:
text = str(value).replace("Z", "+00:00")
parsed = datetime.fromisoformat(text)
return parsed if parsed.tzinfo else parsed.replace(tzinfo=timezone.utc)
except ValueError:
return None
def resolve_review_due_slots(ctx: SteeringEvalContext) -> list[dict[str, Any]]:
now = datetime.now(timezone.utc)
slots: list[dict[str, Any]] = []
for review in ctx.reviews:
if review.get("status") != "planned":
continue
due = _parse_due(review.get("due_at"))
if due is None or due > now:
continue
slots.append(
{
"slot_key": "review.due",
"scope_type": "review",
"scope_id": str(review["id"]),
"title": review.get("title") or "Review",
"summary": "Geplantes Review ist fällig",
"actor_role_hint": "reviewer",
"payload_keys": ["review_id", "checklist_id"],
"priority": "high" if due < now else "normal",
"review_id": str(review["id"]),
"action_id": (
str(review["action_id"]) if review.get("action_id") else None
),
"milestone_id": (
str(review["milestone_id"]) if review.get("milestone_id") else None
),
}
)
return slots