From f270ca66bcd845447aed71842f743282dfc0fc91 Mon Sep 17 00:00:00 2001
From: Autumn-27 <53844290+Autumn-27@users.noreply.github.com>
Date: Tue, 8 Sep 2026 14:25:49 -0400
Subject: [PATCH] =?UTF-8?q?feat(tasks):=20=E4=BB=BB=E5=8A=A1=E5=88=97?=
=?UTF-8?q?=E8=A1=A8=E6=96=B0=E5=A2=9E=E3=80=8C=E8=BF=90=E8=A1=8C=E4=B8=AD?=
=?UTF-8?q?=20Worker=E3=80=8D=E5=88=97?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
TaskListMetricsAll 增加一个 LATERAL 子查询统计 kind='intent' 且
state='running' 的节点数,随 TaskDTO.in_flight 一并返回,口径与任务
详情页概览的「运行中 Worker」完全一致。列表页在「目标进度」后新增该
列,无运行中 Worker 时显示 0。
---
db/exploration.go | 16 ++++++++++++----
server/dto.go | 1 +
server/server.go | 1 +
web/src/app/(main)/function/tasks/page.tsx | 8 ++++++++
4 files changed, 22 insertions(+), 4 deletions(-)
diff --git a/db/exploration.go b/db/exploration.go
index c90a290..a23792c 100644
--- a/db/exploration.go
+++ b/db/exploration.go
@@ -1064,9 +1064,10 @@ type GoalCounts struct{ Total, Met int }
// TaskListMetrics contains the aggregates rendered in task lists.
type TaskListMetrics struct {
- Tokens TokenUsage
- LastActivity int64
- Goals GoalCounts
+ Tokens TokenUsage
+ LastActivity int64
+ Goals GoalCounts
+ RunningIntents int // kind='intent' 且 state='running' 的条数,即运行中 Worker 数
}
// TaskListMetricsAll returns list aggregates for every live task in one query.
@@ -1081,7 +1082,8 @@ func (d *DB) TaskListMetricsAll() (map[int64]TaskListMetrics, error) {
COALESCE(token_metrics.cache_write_tokens,0),
COALESCE(latest_activity.created_at,0),
COALESCE(goal_metrics.total,0),
- COALESCE(goal_metrics.met,0)
+ COALESCE(goal_metrics.met,0),
+ COALESCE(intent_metrics.running,0)
FROM tasks task
LEFT JOIN LATERAL (
SELECT SUM(input_tokens) AS input_tokens,
@@ -1104,6 +1106,11 @@ func (d *DB) TaskListMetricsAll() (map[int64]TaskListMetrics, error) {
FROM exploration_nodes
WHERE exploration_id=task.exploration_id AND kind='goal'
) goal_metrics ON true
+ LEFT JOIN LATERAL (
+ SELECT COUNT(*) AS running
+ FROM exploration_nodes
+ WHERE exploration_id=task.exploration_id AND kind='intent' AND state='running'
+ ) intent_metrics ON true
WHERE task.deleted_at IS NULL`)
if err != nil {
return nil, err
@@ -1122,6 +1129,7 @@ func (d *DB) TaskListMetricsAll() (map[int64]TaskListMetrics, error) {
&metrics.LastActivity,
&metrics.Goals.Total,
&metrics.Goals.Met,
+ &metrics.RunningIntents,
); err != nil {
return nil, err
}
diff --git a/server/dto.go b/server/dto.go
index 596b808..2c77971 100644
--- a/server/dto.go
+++ b/server/dto.go
@@ -50,6 +50,7 @@ type TaskDTO struct {
Tokens TokenTotalDTO `json:"tokens"` // whole-task token consumption
GoalsTotal int `json:"goals_total"`
GoalsMet int `json:"goals_met"`
+ InFlight int `json:"in_flight"` // 运行中 Worker 数(state=running 的意图)
LLMProfileID *int64 `json:"llm_profile_id,omitempty"` // LLM profile used for this task; nil = default
LLMProfileIDs []int64 `json:"llm_profile_ids"`
ActiveLLMProfileID *int64 `json:"active_llm_profile_id,omitempty"`
diff --git a/server/server.go b/server/server.go
index 6fc4354..7abf506 100644
--- a/server/server.go
+++ b/server/server.go
@@ -1064,6 +1064,7 @@ func (s *Server) listTasks(w http.ResponseWriter, r *http.Request) {
}
dto.GoalsTotal = metric.Goals.Total
dto.GoalsMet = metric.Goals.Met
+ dto.InFlight = metric.RunningIntents
dtos = append(dtos, dto)
}
writeJSON(w, 200, map[string]any{"tasks": dtos, "active": active})
diff --git a/web/src/app/(main)/function/tasks/page.tsx b/web/src/app/(main)/function/tasks/page.tsx
index 3eaac38..a5637bf 100644
--- a/web/src/app/(main)/function/tasks/page.tsx
+++ b/web/src/app/(main)/function/tasks/page.tsx
@@ -948,6 +948,7 @@ export default function TasksPage() {
onSort={sortTasksBy}
/>
目标进度
+ 运行中 Worker
—
)}
+
+ {task.in_flight && task.in_flight > 0 ? (
+ {task.in_flight}
+ ) : (
+ 0
+ )}
+
{fmtDateTime(task.created_unix)}