From 8756f8d77fb44f912009ab49b031b0dc3fe8bb9e Mon Sep 17 00:00:00 2001 From: JianFeeeee Date: Mon, 14 Sep 2026 11:07:28 +0800 Subject: [PATCH] =?UTF-8?q?fix(webui):=20=E9=80=9A=E9=81=93=E5=BD=92?= =?UTF-8?q?=E5=B1=9E=E6=8A=8A=E3=80=8C=E6=A0=B9=20agent=20id=E3=80=8D?= =?UTF-8?q?=E4=B8=8E=E9=A9=BB=E7=95=99=E5=AD=90=E5=88=86=E5=BC=80=EF=BC=88?= =?UTF-8?q?=E6=A0=B9=E4=B8=8D=E5=86=8D=E8=A2=AB=E6=A0=87=E6=88=90=E3=80=8C?= =?UTF-8?q?=E9=A9=BB=E7=95=99=E5=AD=90=20main=E3=80=8D=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 实测(创建一个驻留子 uitest 并把 timer 划给它)暴露的归类错误: inputch 的 owner 在登记表里可以是**根 agent 自己的 id**(如 "main")—— child/ 这条就是 owner="main"。前端只按「owner 非空」判为驻留子, 于是根自己那条被标成「驻留子 main」,而同一条通道在 residents 里根本不存在。 改法: - /api/v1/runtime 补 agent_id(根 agent 的 id); - 前端把 owner == 根 id 与 owner == "" 归一成同一组「根 agent / 内核默认」, 只有既非空又非根 id 的才是子容器。 --- internal/plugins/webui/dashboard.js | 22 ++++++++++++++++------ internal/plugins/webui/handler_agents.go | 6 +++++- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/internal/plugins/webui/dashboard.js b/internal/plugins/webui/dashboard.js index 6099e25..2cdef7e 100644 --- a/internal/plugins/webui/dashboard.js +++ b/internal/plugins/webui/dashboard.js @@ -786,8 +786,15 @@ }); var owners = []; var byOwner = {}; + // 根 agent 的 id:登记表里根自己的 owner 就是它(如 "main")。 + // 不把它跟驻留子分开,根自己的通道会被标成「驻留子 main」——实测踩过。 + var rootID = rt.agent_id || ""; + var isChild = function (o) { return o !== "" && o !== rootID; }; inputs.forEach(function (c) { + // owner == 根 agent id 与 owner == "" 是同一件事(都是归根 agent / 内核默认), + // 归一成一组,否则同一个根会画出两个容器。 var o = c.owner || ""; + if (o === rootID) o = ""; if (!byOwner[o]) { byOwner[o] = []; owners.push(o); @@ -798,14 +805,14 @@ // 与「子不存在」无法区分。 residents.forEach(function (r) { var o = r.id || ""; - if (o && !byOwner[o]) { + if (o && o !== rootID && !byOwner[o]) { byOwner[o] = []; owners.push(o); } }); owners.sort(function (a, b) { - if (a === "") return -1; - if (b === "") return 1; + if (a === "" || a === rootID) return -1; + if (b === "" || b === rootID) return 1; return a < b ? -1 : 1; }); if (!owners.length) { @@ -819,10 +826,13 @@ if (r.id === o) res = r; }); } - h += '
'; + var child = isChild(o); + h += '
'; h += '
' + - (o ? "▸ " : "◆ ") + - (o ? __("驻留子 ", "resident ") + escHtml(o) : __("根 agent / 内核默认", "root agent / kernel default")) + + (child ? "▸ " : "◆ ") + + (child + ? __("驻留子 ", "resident ") + escHtml(o) + : __("根 agent", "root agent") + (o ? " " + escHtml(o) : "") + __(" / 内核默认", " / kernel default")) + '' + list.length + " " + __("条通道", "channels") + (res ? " · " + __("轮次", "rounds") + " " + (res.rounds || 0) : "") + (res && res.context_full ? ' ' + __("上下文已满", "ctx full") + "" : "") + diff --git a/internal/plugins/webui/handler_agents.go b/internal/plugins/webui/handler_agents.go index f676f26..806ff45 100644 --- a/internal/plugins/webui/handler_agents.go +++ b/internal/plugins/webui/handler_agents.go @@ -261,7 +261,11 @@ func (h *Handler) handleRuntime(w http.ResponseWriter, r *http.Request) { return } writeJSON(w, http.StatusOK, map[string]interface{}{ - "uptime": ks.Uptime, + "uptime": ks.Uptime, + // agent_id 是**根 agent 的 id**。前端靠它把 inputch 的 owner 归类: + // 归属登记表里根 agent 的 id(如 "main")与驻留子 id 长得一样, + // 不区分就会把根自己的通道标成「驻留子 main」。 + "agent_id": ks.AgentID, "scheduler": ks.Scheduler, "residents": ks.Residents, "channels": ks.Channels,