from __future__ import annotations from datetime import UTC, datetime from typing import Any from sqlalchemy import select from sqlalchemy.orm import Session from app.core.agent_enums import AgentRunStatus from app.models.agent_run import AgentRun from app.services.knowledge_constants import ( KNOWLEDGE_INGEST_STATUS_META, KNOWLEDGE_INGEST_STATUS_PUBLISHED, KNOWLEDGE_INGEST_SYNC_STALE_SECONDS, ) def normalize_ingest_status_code(value: Any) -> int: try: status_code = int(value) except (TypeError, ValueError): return KNOWLEDGE_INGEST_STATUS_PUBLISHED if status_code not in KNOWLEDGE_INGEST_STATUS_META: return KNOWLEDGE_INGEST_STATUS_PUBLISHED return status_code def is_syncing_status_stale(entry: dict[str, Any]) -> bool: raw_value = str(entry.get("ingest_status_updated_at") or "").strip() if not raw_value: return True try: updated_at = datetime.fromisoformat(raw_value) except ValueError: return True if updated_at.tzinfo is None: updated_at = updated_at.replace(tzinfo=UTC) age_seconds = (datetime.now(UTC) - updated_at.astimezone(UTC)).total_seconds() return age_seconds >= KNOWLEDGE_INGEST_SYNC_STALE_SECONDS def should_preserve_syncing_status(entry: dict[str, Any], *, db: Session | None) -> bool: agent_run_id = str(entry.get("ingest_agent_run_id") or "").strip() if not agent_run_id or db is None: return not is_syncing_status_stale(entry) run = db.scalar(select(AgentRun).where(AgentRun.run_id == agent_run_id)) if run is None: return not is_syncing_status_stale(entry) if run.status != AgentRunStatus.RUNNING.value: return False heartbeat_at = str((run.route_json or {}).get("heartbeat_at") or "").strip() if heartbeat_at: probe_entry = {"ingest_status_updated_at": heartbeat_at} return not is_syncing_status_stale(probe_entry) return not is_syncing_status_stale(entry) def resolve_linked_ingest_run_status(entry: dict[str, Any], *, db: Session | None) -> str: agent_run_id = str(entry.get("ingest_agent_run_id") or "").strip() if not agent_run_id or db is None: return "" run = db.scalar(select(AgentRun).where(AgentRun.run_id == agent_run_id)) if run is None: return "" return str(run.status or "").strip()