"""Agent slots for due recurring elements.""" 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_recurring_due_slots(ctx: SteeringEvalContext) -> list[dict[str, Any]]: now = datetime.now(timezone.utc) slots: list[dict[str, Any]] = [] for element in ctx.recurring_elements: if element.get("status") != "active": continue due = _parse_due(element.get("next_due_at")) if due is None or due > now: continue slots.append( { "slot_key": "recurring.due", "scope_type": "recurring_element", "scope_id": str(element["id"]), "title": element.get("title") or "Rhythmus", "summary": "Wiederkehrendes Element ist fällig", "actor_role_hint": "operator", "payload_keys": ["recurring_id", "interval_days"], "priority": "normal", "recurring_element_id": str(element["id"]), } ) return slots