From 5adaf8b9556e30b5de91770c5fc971e6aa7a5a25 Mon Sep 17 00:00:00 2001 From: DBT Date: Sat, 28 Feb 2026 06:42:37 +0000 Subject: [PATCH] autonomy M2 phase2: add idle budget/block stats and source/status filters in task queue UI --- pkg/nodes/registry_server.go | 14 +++++++++++++- webui/src/i18n/index.ts | 4 ++++ webui/src/pages/TaskAudit.tsx | 34 ++++++++++++++++++++++++++++++---- 3 files changed, 47 insertions(+), 5 deletions(-) diff --git a/pkg/nodes/registry_server.go b/pkg/nodes/registry_server.go index cc9fd9f..d989e41 100644 --- a/pkg/nodes/registry_server.go +++ b/pkg/nodes/registry_server.go @@ -1475,7 +1475,19 @@ func (s *RegistryServer) handleWebUITaskQueue(w http.ResponseWriter, r *http.Req } } - _ = json.NewEncoder(w).Encode(map[string]interface{}{"ok": true, "running": running, "items": items}) + stats := map[string]int{"total": len(items), "running": len(running), "idle_round_budget": 0, "active_user": 0, "manual_pause": 0} + for _, it := range items { + reason := fmt.Sprintf("%v", it["block_reason"]) + switch reason { + case "idle_round_budget": + stats["idle_round_budget"]++ + case "active_user": + stats["active_user"]++ + case "manual_pause": + stats["manual_pause"]++ + } + } + _ = json.NewEncoder(w).Encode(map[string]interface{}{"ok": true, "running": running, "items": items, "stats": stats}) } func (s *RegistryServer) handleWebUIExecApprovals(w http.ResponseWriter, r *http.Request) { diff --git a/webui/src/i18n/index.ts b/webui/src/i18n/index.ts index 297d30f..e70c55d 100644 --- a/webui/src/i18n/index.ts +++ b/webui/src/i18n/index.ts @@ -21,6 +21,8 @@ const resources = { mediaSources: 'Media Sources', lastPauseReason: 'Last Pause Reason', lastPauseAt: 'Last Pause Time', + allSources: 'All Sources', + allStatus: 'All Status', error: 'Error', noTaskAudit: 'No task audit records', selectTask: 'Select a task from the left list', @@ -176,6 +178,8 @@ const resources = { mediaSources: '媒体来源', lastPauseReason: '最近暂停原因', lastPauseAt: '最近暂停时间', + allSources: '全部来源', + allStatus: '全部状态', error: '错误', noTaskAudit: '暂无任务审计记录', selectTask: '请从左侧选择任务', diff --git a/webui/src/pages/TaskAudit.tsx b/webui/src/pages/TaskAudit.tsx index d7d4fe1..f6b1520 100644 --- a/webui/src/pages/TaskAudit.tsx +++ b/webui/src/pages/TaskAudit.tsx @@ -30,6 +30,8 @@ const TaskAudit: React.FC = () => { const [items, setItems] = useState([]); const [selected, setSelected] = useState(null); const [loading, setLoading] = useState(false); + const [sourceFilter, setSourceFilter] = useState('all'); + const [statusFilter, setStatusFilter] = useState('all'); const fetchData = async () => { setLoading(true); @@ -53,22 +55,46 @@ const TaskAudit: React.FC = () => { useEffect(() => { fetchData(); }, [q]); + + const filteredItems = useMemo(() => items.filter((it) => { + if (sourceFilter !== 'all' && String(it.source || '-') !== sourceFilter) return false; + if (statusFilter !== 'all' && String(it.status || '-') !== statusFilter) return false; + return true; + }), [items, sourceFilter, statusFilter]); const selectedPretty = useMemo(() => selected ? JSON.stringify(selected, null, 2) : '', [selected]); return (
-
+

{t('taskAudit')}

- +
+ + + +
{t('taskQueue')}
- {items.length === 0 ? ( + {filteredItems.length === 0 ? (
{t('noTaskAudit')}
- ) : items.map((it, idx) => { + ) : filteredItems.map((it, idx) => { const active = selected?.task_id === it.task_id && selected?.time === it.time; return (