diff --git a/panel.js b/panel.js
index 5c3ea8c..de40131 100644
--- a/panel.js
+++ b/panel.js
@@ -2720,10 +2720,6 @@ function _renderMessageTraceWorkspace(state) {
return `
@@ -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) {
最后注入给主 AI 的内容
-
- 这里展示的不是候选记忆,而是这一轮真正拼进主模型上下文的记忆文本。
-
${_escHtml(_formatTaskProfileTime(injectionSnapshot.updatedAt))}
-
-
- 触发来源
- ${_escHtml(injectionSnapshot.sourceLabel || injectionSnapshot.source || "—")}
-
-
- 触发钩子
- ${_escHtml(injectionSnapshot.hookName || "—")}
-
-
- 触发用户输入
- ${_escHtml(triggeredUserMessage || "—")}
-
-
- 选中记忆数
- ${_escHtml(String(injectionSnapshot.selectedNodeIds?.length ?? 0))}
-
-
${_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 `
最后送去提取模型的内容
-
- 这里看的是自动提取真正下发给记忆模型的请求,不只是任务预设模板。
-
${_escHtml(
_formatTaskProfileTime(extractLlmRequest?.updatedAt || extractPromptBuild?.updatedAt),
)}
-
-
- 预设
- ${_escHtml(extractPromptBuild?.profileName || extractPromptBuild?.profileId || "—")}
-
-
- 模型路由
- ${_escHtml(extractLlmRequest?.effectiveRoute?.llm || extractLlmRequest?.route || "—")}
-
-
- 模型
- ${_escHtml(extractLlmRequest?.model || "—")}
-
-
- 消息条数
- ${_escHtml(String(_normalizeDebugMessages(extractLlmRequest?.messages).length))}
-
-
${_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(
{