Simplify message trace panels

This commit is contained in:
Hao19911125
2026-04-04 22:26:08 +08:00
parent 88dfb709bf
commit bfb92a94bf

184
panel.js
View File

@@ -2720,10 +2720,6 @@ function _renderMessageTraceWorkspace(state) {
return `
<div class="bme-task-tab-body">
<div class="bme-task-toolbar-row">
<div class="bme-task-note">
这里看的是最近一轮真实运行留下的痕迹,不是静态配置推演。你关心的两个问题会直接拆开:
“最后注入给主 AI 的记忆文本” 和 “最后送去提取模型的实际请求”。
</div>
<span class="bme-task-pill">${_escHtml(_formatTaskProfileTime(updatedAt))}</span>
</div>
@@ -2747,10 +2743,11 @@ function _renderMessageTraceRecallCard(state) {
: [];
const triggeredUserMessage =
_extractTriggeredUserMessageFromRecentMessages(recentMessages) ||
_findMarkdownSectionContent(
_getLastDebugMessageContent(recallLlmRequest?.messages, "user"),
["用户最新输入"],
);
_getLastDebugMessageContent(recallLlmRequest?.messages, "user");
const hostPayloadText = _buildMainAiTraceText(
triggeredUserMessage,
injectionSnapshot?.injectionText || "",
);
if (!injectionSnapshot) {
return `
@@ -2765,50 +2762,24 @@ function _renderMessageTraceRecallCard(state) {
<div class="bme-config-card-head">
<div>
<div class="bme-config-card-title">最后注入给主 AI 的内容</div>
<div class="bme-config-card-subtitle">
这里展示的不是候选记忆,而是这一轮真正拼进主模型上下文的记忆文本。
</div>
</div>
<span class="bme-task-pill">${_escHtml(_formatTaskProfileTime(injectionSnapshot.updatedAt))}</span>
</div>
<div class="bme-debug-kv-list">
<div class="bme-debug-kv-item">
<span class="bme-debug-kv-key">触发来源</span>
<span class="bme-debug-kv-value">${_escHtml(injectionSnapshot.sourceLabel || injectionSnapshot.source || "—")}</span>
</div>
<div class="bme-debug-kv-item">
<span class="bme-debug-kv-key">触发钩子</span>
<span class="bme-debug-kv-value">${_escHtml(injectionSnapshot.hookName || "—")}</span>
</div>
<div class="bme-debug-kv-item">
<span class="bme-debug-kv-key">触发用户输入</span>
<span class="bme-debug-kv-value">${_escHtml(triggeredUserMessage || "—")}</span>
</div>
<div class="bme-debug-kv-item">
<span class="bme-debug-kv-key">选中记忆数</span>
<span class="bme-debug-kv-value">${_escHtml(String(injectionSnapshot.selectedNodeIds?.length ?? 0))}</span>
</div>
</div>
${_renderMessageTraceTextBlock(
"最终注入文本",
injectionSnapshot.injectionText || "",
"这次没有生成可注入的记忆文本。",
"发送给主 AI 的内容",
hostPayloadText,
"这次没有捕获到主 AI 侧的注入内容。",
)}
${_renderDebugDetails(
"召回参考上下文",
recentMessages.length ? recentMessages.join("\n") : "",
)}
${_renderDebugDetails(
"召回精排实际消息序列",
_stringifyTraceMessages(recallLlmRequest?.messages),
)}
${_renderDebugDetails("原始注入快照", injectionSnapshot)}
`;
}
function _renderMessageTraceExtractCard(state) {
const extractLlmRequest = state.extractLlmRequest || null;
const extractPromptBuild = state.extractPromptBuild || null;
const extractPayloadText = _buildTraceMessagePayloadText(
extractLlmRequest?.messages,
extractPromptBuild,
);
if (!extractLlmRequest && !extractPromptBuild) {
return `
@@ -2819,56 +2790,20 @@ function _renderMessageTraceExtractCard(state) {
`;
}
const systemPrompt =
_getLastDebugMessageContent(extractLlmRequest?.messages, "system") ||
extractPromptBuild?.systemPrompt ||
"";
const userPrompt = _getLastDebugMessageContent(extractLlmRequest?.messages, "user");
const dialogueText =
_findMarkdownSectionContent(userPrompt, ["当前对话内容"]) || userPrompt;
return `
<div class="bme-config-card-head">
<div>
<div class="bme-config-card-title">最后送去提取模型的内容</div>
<div class="bme-config-card-subtitle">
这里看的是自动提取真正下发给记忆模型的请求,不只是任务预设模板。
</div>
</div>
<span class="bme-task-pill">${_escHtml(
_formatTaskProfileTime(extractLlmRequest?.updatedAt || extractPromptBuild?.updatedAt),
)}</span>
</div>
<div class="bme-debug-kv-list">
<div class="bme-debug-kv-item">
<span class="bme-debug-kv-key">预设</span>
<span class="bme-debug-kv-value">${_escHtml(extractPromptBuild?.profileName || extractPromptBuild?.profileId || "—")}</span>
</div>
<div class="bme-debug-kv-item">
<span class="bme-debug-kv-key">模型路由</span>
<span class="bme-debug-kv-value">${_escHtml(extractLlmRequest?.effectiveRoute?.llm || extractLlmRequest?.route || "—")}</span>
</div>
<div class="bme-debug-kv-item">
<span class="bme-debug-kv-key">模型</span>
<span class="bme-debug-kv-value">${_escHtml(extractLlmRequest?.model || "—")}</span>
</div>
<div class="bme-debug-kv-item">
<span class="bme-debug-kv-key">消息条数</span>
<span class="bme-debug-kv-value">${_escHtml(String(_normalizeDebugMessages(extractLlmRequest?.messages).length))}</span>
</div>
</div>
${_renderMessageTraceTextBlock(
"送去提取的对话正文",
dialogueText,
"这次没有捕获到提取用户提示词。",
"送去提取模型的内容",
extractPayloadText,
"这次没有捕获到提取请求内容。",
)}
${_renderDebugDetails("提取系统提示词(兼容视图)", systemPrompt)}
${_renderDebugDetails("提取用户提示词(完整)", userPrompt)}
${_renderDebugDetails(
"提取实际消息序列",
_stringifyTraceMessages(extractLlmRequest?.messages),
)}
${_renderDebugDetails("提取 Prompt 组装快照", extractPromptBuild)}
`;
}
@@ -2916,11 +2851,49 @@ function _stringifyTraceMessages(messages = []) {
return normalizedMessages
.map(
(message, index) => `[${index + 1}] ${message.role}\n${message.content}`,
(message) => `${message.role}\n${message.content}`,
)
.join("\n\n---\n\n");
}
function _buildMainAiTraceText(triggeredUserMessage = "", injectionText = "") {
const sections = [];
const normalizedUserMessage = String(triggeredUserMessage || "").trim();
const normalizedInjectionText = String(injectionText || "").trim();
if (normalizedUserMessage) {
sections.push(`【user】\n${normalizedUserMessage}`);
}
if (normalizedInjectionText) {
sections.push(`【memory injection】\n${normalizedInjectionText}`);
}
return sections.join("\n\n---\n\n").trim();
}
function _buildTraceMessagePayloadText(messages = [], promptBuild = null) {
const normalizedMessages = _normalizeDebugMessages(messages);
if (normalizedMessages.length) {
return _stringifyTraceMessages(normalizedMessages);
}
const fallbackMessages = [];
const fallbackSystemPrompt = String(promptBuild?.systemPrompt || "").trim();
if (fallbackSystemPrompt) {
fallbackMessages.push({ role: "system", content: fallbackSystemPrompt });
}
for (const message of promptBuild?.privateTaskMessages || []) {
if (!message || typeof message !== "object") continue;
const role = String(message.role || "").trim().toLowerCase();
const content = String(message.content || "").trim();
if (!role || !content) continue;
fallbackMessages.push({ role, content });
}
return _stringifyTraceMessages(fallbackMessages);
}
function _extractTriggeredUserMessageFromRecentMessages(recentMessages = []) {
if (!Array.isArray(recentMessages)) return "";
@@ -2934,55 +2907,6 @@ function _extractTriggeredUserMessageFromRecentMessages(recentMessages = []) {
return "";
}
function _extractMarkdownSections(text = "") {
const normalized = String(text || "");
if (!normalized.trim()) return [];
const headingRegex = /^#{1,6}\s*(.+?)\s*$/gm;
const sections = [];
let currentTitle = "";
let bodyStart = 0;
let match = headingRegex.exec(normalized);
while (match) {
if (currentTitle) {
sections.push({
title: currentTitle,
content: normalized.slice(bodyStart, match.index).trim(),
});
}
currentTitle = String(match[1] || "").trim();
bodyStart = headingRegex.lastIndex;
match = headingRegex.exec(normalized);
}
if (currentTitle) {
sections.push({
title: currentTitle,
content: normalized.slice(bodyStart).trim(),
});
}
return sections;
}
function _findMarkdownSectionContent(text = "", titleHints = []) {
const hints = Array.isArray(titleHints)
? titleHints.map((item) => String(item || "").trim()).filter(Boolean)
: [];
if (!hints.length) return "";
const sections = _extractMarkdownSections(text);
for (const section of sections) {
const title = String(section?.title || "");
if (hints.some((hint) => title.includes(hint))) {
return String(section?.content || "").trim();
}
}
return "";
}
function _patchTaskProfiles(taskProfiles, extraPatch = {}, options = {}) {
return _patchSettings(
{