diff --git a/changelogs/unreleased.md b/changelogs/unreleased.md
index dc3d245cc..8246867b2 100644
--- a/changelogs/unreleased.md
+++ b/changelogs/unreleased.md
@@ -1,5 +1,7 @@
# Unreleased
+- Add independent Group chat / Private chat chips to the trace Type column, using summary message types with a legacy UMO fallback and leaving unknown types unlabeled.
+
- Reduce trace table header height to 40px using Vuetify's native header-height variable; preserve body row and pager sizing.
- Show the Tokens card total with two-decimal k/M notation while keeping precise counts in its tooltip.
diff --git a/dashboard/src/components/shared/TraceDisplayer.vue b/dashboard/src/components/shared/TraceDisplayer.vue
index 3558d95ce..bdaa7f1fd 100644
--- a/dashboard/src/components/shared/TraceDisplayer.vue
+++ b/dashboard/src/components/shared/TraceDisplayer.vue
@@ -159,7 +159,7 @@ const traceHeaders = computed(() => [
{ title: tm("columns.timestamp"), key: "timestamp", width: 160 },
{ title: tm("columns.duration"), key: "duration", width: 120 },
{ title: tm("columns.message"), key: "message", minWidth: 240 },
- { title: tm("columns.category"), key: "category", width: 150, minWidth: 150, headerProps: { class: "text-no-wrap" } },
+ { title: tm("columns.category"), key: "category", width: 220, minWidth: 220, headerProps: { class: "text-no-wrap" } },
{ title: "UMO", key: "umo", minWidth: 240 },
{ title: tm("columns.sender"), key: "sender", minWidth: 120 },
{ title: "Spans", key: "spans", width: 80 },
@@ -347,6 +347,7 @@ function normalizeTracePayload(payload) {
const meta = {
span_id: summary.trace_id, name: summary.name, model_version: 3,
umo: attrs["astrbot.umo"] || "", sender_name: attrs["astrbot.sender_name"] || "",
+ message_type: attrs["astrbot.message_type"] || attrs["astrbot.umo"]?.split(":")[1] || "",
message_outline: attrs["astrbot.message_outline"] || "",
plugin_names: attrs["astrbot.plugins"] || "",
platform_id: attrs["astrbot.platform_id"] || "",
@@ -459,6 +460,7 @@ function processNewTraces(newTraces) {
}
} else {
event.umo = event.umo || trace.umo || "";
+ event.message_type = trace.fields?.message_type || event.message_type || event.umo.split(":")[1] || "";
event.sender_name = event.sender_name || trace.sender_name || "";
event.message_outline = event.message_outline || trace.message_outline || "";
event.platform_id = trace.fields?.platform_id || event.platform_id;
@@ -903,6 +905,8 @@ onBeforeUnmount(() => {
{{ tm("classification.agent") }}
{{ tm("classification.command") }}
+ {{ tm("classification.group") }}
+ {{ tm("classification.private") }}
diff --git a/dashboard/src/i18n/locales/en-US/features/trace.json b/dashboard/src/i18n/locales/en-US/features/trace.json
index 83eabf475..aabc3615f 100644
--- a/dashboard/src/i18n/locales/en-US/features/trace.json
+++ b/dashboard/src/i18n/locales/en-US/features/trace.json
@@ -71,7 +71,9 @@
},
"classification": {
"agent": "Agent",
- "command": "Command"
+ "command": "Command",
+ "group": "Group chat",
+ "private": "Private chat"
},
"columns": {
"category": "Type",
diff --git a/dashboard/src/i18n/locales/ja-JP/features/trace.json b/dashboard/src/i18n/locales/ja-JP/features/trace.json
index bc79e1c00..6c376c7a2 100644
--- a/dashboard/src/i18n/locales/ja-JP/features/trace.json
+++ b/dashboard/src/i18n/locales/ja-JP/features/trace.json
@@ -71,7 +71,9 @@
},
"classification": {
"agent": "Agent",
- "command": "コマンド"
+ "command": "コマンド",
+ "group": "グループチャット",
+ "private": "個人チャット"
},
"columns": {
"category": "種類",
diff --git a/dashboard/src/i18n/locales/ru-RU/features/trace.json b/dashboard/src/i18n/locales/ru-RU/features/trace.json
index 054cbb0f9..912358672 100644
--- a/dashboard/src/i18n/locales/ru-RU/features/trace.json
+++ b/dashboard/src/i18n/locales/ru-RU/features/trace.json
@@ -71,7 +71,9 @@
},
"classification": {
"agent": "Agent",
- "command": "Команда"
+ "command": "Команда",
+ "group": "Групповой чат",
+ "private": "Личный чат"
},
"columns": {
"category": "Тип",
diff --git a/dashboard/src/i18n/locales/zh-CN/features/trace.json b/dashboard/src/i18n/locales/zh-CN/features/trace.json
index 52be0751b..643cf5e5a 100644
--- a/dashboard/src/i18n/locales/zh-CN/features/trace.json
+++ b/dashboard/src/i18n/locales/zh-CN/features/trace.json
@@ -71,7 +71,9 @@
},
"classification": {
"agent": "Agent",
- "command": "指令"
+ "command": "指令",
+ "group": "群聊",
+ "private": "私聊"
},
"columns": {
"category": "类型",
diff --git a/dashboard/tests/traceList.test.mjs b/dashboard/tests/traceList.test.mjs
index 788c01c2d..92875673a 100644
--- a/dashboard/tests/traceList.test.mjs
+++ b/dashboard/tests/traceList.test.mjs
@@ -59,6 +59,21 @@ function canonical(id, stamp = "2000000000", completed = true) {
};
}
+test("chat type prefers summary metadata and falls back to legacy UMO", (t) => {
+ const state = setup(t);
+ const trace = canonical("c".repeat(32));
+ trace.attributes["astrbot.umo"] = "platform:GroupMessage:session:with:colons";
+ trace.attributes["astrbot.message_type"] = "FriendMessage";
+ state.processNewTraces([{ trace }]);
+ assert.equal(state.events.value[0].message_type, "FriendMessage");
+ const legacy = canonical("d".repeat(32));
+ legacy.attributes["astrbot.umo"] = "platform:GroupMessage:session";
+ state.processNewTraces([{ trace: legacy }]);
+ assert.equal(state.events.value[0].message_type, "GroupMessage");
+ state.processNewTraces([record("raw", "event_received", 3, { message_type: "OtherMessage" })]);
+ assert.equal(state.events.value[0].message_type, "OtherMessage");
+});
+
test("canonical live updates keep summaries only and count real spans, not events", async (t) => {
const state = setup(t);
const trace = canonical("a".repeat(32));
diff --git a/docs/en/use/webui.md b/docs/en/use/webui.md
index d4a15f892..3f23e44e9 100644
--- a/docs/en/use/webui.md
+++ b/docs/en/use/webui.md
@@ -174,7 +174,7 @@ The toolbar contains search, fullscreen, font-size controls, and `Install Pip pa
Traces containing Agent calls add a borderless Tokens statistics card. Its total sums this execution's input (including cached input) and output, displayed with two-decimal k/M notation while the tooltip retains exact counts; hover or focus to inspect input, output, and cached-input counts. Only the latest cumulative snapshot per Agent is used, and separate Agents are summed. Unavailable usage shows an em dash rather than a reported zero.
-The Type column precedes UMO. Blue Agent indicates an Agent call; green Command indicates a command-handler call. Both can appear independently on the same trace. Ordinary listeners and event hooks do not count as commands. Summaries provide these flags; legacy command flags are derived for the current page without opening each trace's details.
+The Type column precedes UMO. Blue Agent indicates an Agent call; green Command indicates a command-handler call. Neutral Group chat / Private chat chips appear independently alongside them. Ordinary listeners and event hooks do not count as commands. Message type comes from the summary, falling back to UMO for older records; unknown types have no chat chip. Legacy command flags are derived for the current page without opening each trace's details.
New spans identify calls with `astrbot.kind` and describe execution through timestamps and status. They no longer store `astrbot.action`, `astrbot.end_action`, or `astrbot.duration_ms`; duration is calculated from nanosecond timestamps and `astrbot.handler_type` remains. Existing trace history stays readable without rewriting stored records.
diff --git a/docs/zh/use/webui.md b/docs/zh/use/webui.md
index 25316de93..2e002fea4 100644
--- a/docs/zh/use/webui.md
+++ b/docs/zh/use/webui.md
@@ -174,7 +174,7 @@ ChatUI 支持以下常用能力:
包含 Agent 调用时,详情统计区增加无边框的 Tokens 卡片,展示本轮输入(含缓存输入)与输出的累计总量,以两位小数的 k/M 格式显示,悬浮提示保留精确数量;悬停或键盘聚焦可查看输入、输出及缓存命中明细。同一 Agent 的累计快照只取最新一份,多个 Agent 分别累计。没有已上报用量时显示“—”,不按 0 处理。
-UMO 前新增“类型”列:蓝色 Agent 表示 Agent 调用,绿色“指令”表示指令处理器调用。同一追踪可同时显示两个标签;普通监听器和事件钩子不算作指令。类型由追踪摘要提供,旧记录的指令标记按当前页数据推导,无需逐条打开详情。
+UMO 前新增“类型”列:蓝色 Agent 表示 Agent 调用,绿色“指令”表示指令处理器调用;群聊/私聊使用中性标签独立显示。同一追踪可同时显示这些标签;普通监听器和事件钩子不算作指令。消息类型优先读取追踪摘要,旧记录从 UMO 推导,无法确定时不显示群聊/私聊标签。旧记录的指令标记按当前页数据推导,无需逐条打开详情。
新 Span 使用 `astrbot.kind` 表示调用类型,起止时间和状态表示执行结果;不再存储 `astrbot.action`、`astrbot.end_action` 或 `astrbot.duration_ms`。耗时由纳秒起止时间计算,`astrbot.handler_type` 保留。旧追踪仍可读取,历史数据库记录不会自动重写。