feat: show group and private chat trace types

This commit is contained in:
Soulter
2026-10-14 13:37:59 +08:00
parent e2f6c81562
commit 4e6a8e8b73
9 changed files with 36 additions and 7 deletions
+2
View File
@@ -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.
@@ -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(() => {
<div class="trace-category-chips">
<v-chip v-if="matchesFilter(event, 'models')" size="small" variant="flat" color="#1976D2">{{ tm("classification.agent") }}</v-chip>
<v-chip v-if="event.has_commands ?? event.records.some((record) => record.kind === 'plugin_handler' && record.fields.handler_category === 'command')" size="small" variant="flat" color="#2E7D32">{{ tm("classification.command") }}</v-chip>
<v-chip v-if="event.message_type === 'GroupMessage'" size="small" variant="tonal">{{ tm("classification.group") }}</v-chip>
<v-chip v-else-if="event.message_type === 'FriendMessage'" size="small" variant="tonal">{{ tm("classification.private") }}</v-chip>
</div>
</template>
<template #item.umo="{ item: { event } }">
@@ -71,7 +71,9 @@
},
"classification": {
"agent": "Agent",
"command": "Command"
"command": "Command",
"group": "Group chat",
"private": "Private chat"
},
"columns": {
"category": "Type",
@@ -71,7 +71,9 @@
},
"classification": {
"agent": "Agent",
"command": "コマンド"
"command": "コマンド",
"group": "グループチャット",
"private": "個人チャット"
},
"columns": {
"category": "種類",
@@ -71,7 +71,9 @@
},
"classification": {
"agent": "Agent",
"command": "Команда"
"command": "Команда",
"group": "Групповой чат",
"private": "Личный чат"
},
"columns": {
"category": "Тип",
@@ -71,7 +71,9 @@
},
"classification": {
"agent": "Agent",
"command": "指令"
"command": "指令",
"group": "群聊",
"private": "私聊"
},
"columns": {
"category": "类型",
+15
View File
@@ -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));
+1 -1
View File
@@ -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.
+1 -1
View File
@@ -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` 保留。旧追踪仍可读取,历史数据库记录不会自动重写。