mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-21 03:39:54 +00:00
fix(kanban): task_age() tolerates ISO-8601 timestamps
Prevents ValueError crash in dashboard get_board() when a task has an ISO timestamp (e.g. "2026-05-10T15:00:00Z") instead of a unix epoch int. Adds _to_epoch() helper that normalises both formats.
This commit is contained in:
committed by
Teknium
parent
ca8126bd53
commit
d8ad431de8
+28
-10
@@ -4756,26 +4756,44 @@ def board_stats(conn: sqlite3.Connection) -> dict:
|
||||
}
|
||||
|
||||
|
||||
def _safe_int(val: Optional[str]) -> Optional[int]:
|
||||
"""Parse a timestamp field to int, returning None on garbage like '%s'."""
|
||||
def _to_epoch(val) -> Optional[int]:
|
||||
"""Normalise a timestamp to unix epoch seconds.
|
||||
|
||||
Accepts ints (pass-through), numeric strings, and ISO-8601 strings.
|
||||
Returns ``None`` for ``None`` / empty values.
|
||||
"""
|
||||
if val is None:
|
||||
return None
|
||||
try:
|
||||
if isinstance(val, int):
|
||||
return val
|
||||
if isinstance(val, float):
|
||||
return int(val)
|
||||
except (ValueError, TypeError):
|
||||
s = str(val).strip()
|
||||
if not s:
|
||||
return None
|
||||
try:
|
||||
return int(s)
|
||||
except ValueError:
|
||||
pass
|
||||
# ISO-8601 fallback (e.g. '2026-05-10T15:00:00Z')
|
||||
try:
|
||||
from datetime import datetime, timezone
|
||||
dt = datetime.fromisoformat(s.replace("Z", "+00:00"))
|
||||
return int(dt.timestamp())
|
||||
except (ValueError, OSError):
|
||||
return None
|
||||
|
||||
|
||||
def task_age(task: Task) -> dict:
|
||||
"""Return age metrics for a single task. All values are seconds or None."""
|
||||
now = int(time.time())
|
||||
created = _safe_int(task.created_at)
|
||||
started = _safe_int(task.started_at)
|
||||
completed = _safe_int(task.completed_at)
|
||||
age_since_created = now - created if created else None
|
||||
age_since_started = now - started if started else None
|
||||
_c = _to_epoch(task.created_at)
|
||||
_s = _to_epoch(task.started_at)
|
||||
_co = _to_epoch(task.completed_at)
|
||||
age_since_created = now - _c if _c is not None else None
|
||||
age_since_started = now - _s if _s is not None else None
|
||||
time_to_complete = (
|
||||
completed - (started or created) if completed else None
|
||||
_co - (_s or _c) if _co is not None else None
|
||||
)
|
||||
return {
|
||||
"created_age_seconds": age_since_created,
|
||||
|
||||
Reference in New Issue
Block a user