console: 对话只保留一处实时单列(ChatGPT 式)
根因:ConversationSection 同时渲染 TracePanel(prompt + 全部链路条目)和 ContinuePanel(GET /chat-history, 服务端已把 prompt + 继续 + 后续 + 全部链路种类按时间 合并、并去掉了后续消息回声),简单任务的两份名单 显示同一组用户 + 助手卡片,看起来就是对话重复。 改法:删 TracePanel 名单,只留 ContinuePanel 这一列; TracePanel 唯一不重复的控件(链路类型筛选、下载完整 链路)移到这一列顶部,筛选只过滤链路消息、用户消息 恒保留;实时性不丢:基础是 10 秒轮询的 chat-history, SSE 新链路条目按 id 去重合并进来,轮询拿到后不再 重复;无 chat-history 的旧服务端回退路径也改成渲染 全部链路种类(不再只渲染 message),并跳过 fu- 回声。
This commit is contained in:
1 parent
b306b56517
commit
c192c5dec8
6 files changed
+95
-92
No files matched your search
@@ -2,7 +2,7 @@ import type { TraceEntry } from "../../api/types";
|
||||
import { traceLineText } from "../../api/client";
|
||||
|
||||
export type ChatRole = "user" | "assistant" | "tool" | "status";
|
||||
export interface ChatMessage { id: string; role: ChatRole; text: string; label?: string }
|
||||
export interface ChatMessage { id: string; role: ChatRole; text: string; label?: string; kind?: string }
|
||||
|
||||
// Mapping is by live trace kind ONLY. Trace entries carry no timestamp
|
||||
// and no sender role in the live file, so no role is invented from
|
||||
@@ -18,15 +18,15 @@ export function traceEntryToChatMessage(e: TraceEntry, i: number): ChatMessage {
|
||||
// 成模型没写完(2026-10-29 实弹:468 字 final_answer 断在 fu)。
|
||||
// 完整回复在任务的 result_text(右侧详情),不在链路条目里。
|
||||
const text = (e.phase ? "[" + e.phase + "] " : "") + (e.text || "");
|
||||
return { id, role: "assistant", text: e.truncated ? text + "\n(链路摘要已截断至 300 字,完整回复见右侧任务结果)" : text, label: "助手" };
|
||||
return { id, role: "assistant", kind: e.kind, text: e.truncated ? text + "\n(链路摘要已截断至 300 字,完整回复见右侧任务结果)" : text, label: "助手" };
|
||||
}
|
||||
if (e.kind === "exec" || e.kind === "file" || e.kind === "tool" || e.kind === "call") {
|
||||
const label = e.kind === "exec" ? "命令" : e.kind === "file" ? "文件" : e.kind === "tool" ? "工具" : "调用";
|
||||
return { id, role: "tool", text: traceLineText(e), label };
|
||||
return { id, role: "tool", kind: e.kind, text: traceLineText(e), label };
|
||||
}
|
||||
if (e.kind === "plan") return { id, role: "status", text: e.text || "" };
|
||||
if (e.kind === "reasoning") return { id, role: "status", text: "思考:" + (e.summary || "") };
|
||||
if (e.kind === "agent-start") return { id, role: "status", text: "子代理开始:" + (e.name || "") + (e.prompt ? "(" + e.prompt + ")" : "") };
|
||||
if (e.kind === "agent-done") return { id, role: "status", text: "子代理结束:" + (e.name || "") + " " + (e.status || "") };
|
||||
return { id, role: "status", text: traceLineText(e) };
|
||||
if (e.kind === "plan") return { id, role: "status", kind: e.kind, text: e.text || "" };
|
||||
if (e.kind === "reasoning") return { id, role: "status", kind: e.kind, text: "思考:" + (e.summary || "") };
|
||||
if (e.kind === "agent-start") return { id, role: "status", kind: e.kind, text: "子代理开始:" + (e.name || "") + (e.prompt ? "(" + e.prompt + ")" : "") };
|
||||
if (e.kind === "agent-done") return { id, role: "status", kind: e.kind, text: "子代理结束:" + (e.name || "") + " " + (e.status || "") };
|
||||
return { id, role: "status", kind: e.kind, text: traceLineText(e) };
|
||||
}
|
||||
Reference in new issue
Block a user