From 24c2c43770623a1cb65764797671635130c60a04 Mon Sep 17 00:00:00 2001 From: pewdiepie-archdaemon Date: Tue, 30 Jun 2026 01:16:41 +0000 Subject: [PATCH] Speed up task activity load --- routes/task_routes.py | 15 +++++++++++++-- static/js/tasks.js | 16 +++++++++++++++- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/routes/task_routes.py b/routes/task_routes.py index 4d0496886..fb1a7c746 100644 --- a/routes/task_routes.py +++ b/routes/task_routes.py @@ -894,10 +894,11 @@ def setup_task_routes(task_scheduler) -> APIRouter: return {"ok": True, "message": "Task stopped"} @router.get("/runs/recent") - async def list_recent_runs(request: Request, limit: int = 50): + async def list_recent_runs(request: Request, limit: int = 50, max_result_chars: int = 6000): """Recent task runs across ALL tasks for this owner. Drives the Activity view.""" user = _owner(request) limit = max(1, min(limit, 200)) + max_result_chars = max(500, min(max_result_chars, 20000)) db = SessionLocal() try: q = db.query(TaskRun, ScheduledTask).join( @@ -931,10 +932,20 @@ def setup_task_routes(task_scheduler) -> APIRouter: deduped.append((r, t)) if len(deduped) >= limit: break + + def _clip_run(r: TaskRun) -> dict: + d = _run_to_dict(r) + for key in ("result", "error"): + val = d.get(key) + if isinstance(val, str) and len(val) > max_result_chars: + d[key] = val[:max_result_chars].rstrip() + "\n\n[Activity preview truncated]" + return d + return { + "has_more": len(rows) > len(deduped), "runs": [ { - **_run_to_dict(r), + **_clip_run(r), "task_name": _display_task_name(t), "task_type": t.task_type or "llm", "action": t.action, diff --git a/static/js/tasks.js b/static/js/tasks.js index c8ae8feb3..9bd09104f 100644 --- a/static/js/tasks.js +++ b/static/js/tasks.js @@ -2001,6 +2001,17 @@ async function _renderActivityView() { return; } list.innerHTML = _stackActivityEntries(filtered).map(_renderActivityEntry).join(''); + if (_activityHasMore && !q) { + list.insertAdjacentHTML('beforeend', ` + + `); + list.querySelector('#tasks-activity-load-more')?.addEventListener('click', () => { + _activityLimit = Math.min(200, _activityLimit + 40); + _renderActivityView(); + }); + } _wireActivityRows(list); }; @@ -2060,10 +2071,11 @@ async function _renderActivityView() { } try { - const res = await fetch(`${API_BASE}/api/tasks/runs/recent?limit=100`, { credentials: 'same-origin' }); + const res = await fetch(`${API_BASE}/api/tasks/runs/recent?limit=${_activityLimit}&max_result_chars=6000`, { credentials: 'same-origin' }); if (!res.ok) throw new Error(`HTTP ${res.status}`); const data = await res.json(); const runs = data.runs || []; + _activityHasMore = !!data.has_more && _activityLimit < 200; const list = document.getElementById('tasks-activity-list'); if (!list) return; if (runs.length === 0) { @@ -2105,6 +2117,8 @@ async function _renderActivityView() { } let _activityEntries = []; +let _activityLimit = 40; +let _activityHasMore = false; function _stackActivityEntries(entries) { const out = [];