Skip to content

修复 Agent 扫描记忆标题及详情页用户内容展示 - #725

Merged
origami-chen merged 7 commits into
MemTensor:v1.2.6from
Orsted290:fix-agent-source-memory-titles-v126
Oct 28, 2026
Merged

origami-chen merged 7 commits into
MemTensor:v1.2.6from
Orsted290:fix-agent-source-memory-titles-v126

Conversation

@Orsted290

Copy link
Copy Markdown
Contributor

问题定位

Agent 扫描记忆时,用户消息开头可能带有时间戳、浏览器上下文、技能或附件等来源信息,导致列表标题重复显示标签;摘要失败或为空时,回退正文也可能重新泄漏这些内容。部分带来源封装的记录在详情页无法正确显示“用户”内容。

修改内容

  • 在导入标题和列表预览中统一提取语义用户文本,跳过已识别的来源上下文,优先使用用户真实请求。普通 HTML、引用和代码中的标签仍保留原文。
  • 摘要处理中、失败或为空时优先使用读模型提供的 sourceText;没有有效用户请求时显示记录 ID,不使用助手回复作为标题。
  • 详情页正确呈现带来源封装的用户原文,并将字面 HTML 安全显示为文本;仅在记忆详情和任务对话中启用该展示方式。
  • 补充导入、读模型、前端展示和 Codex source-turn 回归用例。v1.2.6 已有按来源模型元数据过滤 Codex 自动审查回合的逻辑;本分支补充相邻真实回合及无模型证据时不误过滤的测试,不清理历史存量记录。

测试结果

  • Node 22.23.3:Memory 定向测试 3 个文件、83 项通过;桌面前端定向测试 4 个文件、74 项通过;Codex source-turn 测试 22 项通过。
  • npm run lint 通过,git diff --check upstream/v1.2.6...HEAD 通过。
  • 全仓 npm run typecheck 未完成:复用的本地依赖缓存缺少 monaco-editor 和 Electron 类型,前端与桌面包类型检查因此无法完整执行。
  • 原修复分支的 macOS 安装版曾用六条匿名合成样例完成列表、详情和重启验收;本次重基至 v1.2.6 后未重新打包安装,因此 v1.2.6 基线安装版验收未验证。

范围说明

本 PR 只包含标题提取、详情页用户内容展示及对应回归测试;不包含历史 Codex 自动审查记录的批量清理。

return summary;
if (item.kind === "trace") {
// All processing states use the read model preview, never raw source text.
return summary ?? waitingPrimaryText(item);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

旧记录没有摘要时,原文标签仍会盖过已清洗的用户请求

问题
打开一条尚无有效摘要、也没有生成标题的旧版 L1 记录,如果它以未分段的原文保存,例如 浏览器上下文\n请修复扫描标题,本次读模型已经能提取出 sourceText = 请修复扫描标题,但当记录处于 ready 或 failed 时,列表标题仍显示浏览器标签和上下文。没有有效用户请求的同类记录,也不能可靠回退到记录 ID。

原因
数据库没有摘要,并不意味着前端收到的 item.summary 为空。列表读取先经过 Repositories.toListItem();其中 listSummaryForMemory() 在没有存储摘要时,会把 memoryValue 的第一条可读行填入 summary。详情的 detailSummaryForMemory() 也有正文回退。与此同时,本次 displayFieldsForMemory() 把来源封装过滤掉,另行给出正确的 sourceText。
前端 readySummary() 无法区分真正存储的摘要和这条从正文回填的内容,会接受浏览器标签。这里的 summary ?? waitingPrimaryText(item) 因而优先返回原文,使已经清洗的 sourceText 没有机会使用。新增前端测试直接把 summary 设置为 "" 或占位文案,绕过了服务端实际回填过程,所以未覆盖这条链路。

建议做法
对原始对话记忆统一列表和详情的摘要读取约定:没有有效的存储摘要时,服务返回空的 summary,不要拿原文首行填充。sourceText 是适合标题预览的用户请求文本,这个字段原本就存在,本 PR 改进了它的来源封装过滤规则。没有生成标题或有效摘要时,让前端已有逻辑回退到 sourceText;连有效请求也没有时再显示记录 ID。无需把 sourceText 再伪装成摘要,也不要在前端另加一套标签过滤。
调整列表 listSummaryForMemory()、详情 detailSummaryForMemory() 与前端 displayMemoryTitle() 的衔接,并核对读取详情摘要的 panel/task 调用方。改动限定在此次原始对话摘要回退问题,保留聚合记忆、工作记忆等其它类型的原有字段含义。

Comment thread Memory/src/utils/text.ts Outdated

// Only source-protocol envelopes at the beginning of a message are recognized.
// Once ordinary prose, HTML, a quote or code starts, its contents stay literal.
const SOURCE_ENVELOPE = /^(?:[ \t]*\r?\n)* {0,3}<(timestamp|system_notification|system_reminder|system-reminder|image_files|manually_attached_skills|attached_files|external_links|in-app-browser-context|user_query)(?=[\s/>])(?:[^>"']|"[^"]*"|'[^']*')*>/i;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

问题**

查看尚在等待摘要的 Claude Code 记忆时,如果用户消息先包含粘贴内容封装,随后才写实际请求,列表仍会把封装的首行标签当作标题。例如以下输入(省略了与复现无关的粘贴正文):

<pasted_content id="261b">
[粘贴正文]
</pasted_content id="261b">

这条我手动改了,你调整下格式就行

记录没有生成标题或有效摘要、处理状态为 summary_pending 时,预期标题是“这条我手动改了,你调整下格式就行”;当前 head 的读模型和列表组件回放结果仍为 <pasted_content id="261b">。闭标签带属性是需要兼容的来源格式。附件 PR-725-CR-002-记忆片段.txt 包含必要输入、处理状态和复现步骤,不依赖特定数据库即可验证。

原因

共享的 semanticUserText() 负责跳过消息开头的来源封装,但白名单没有 pasted_content。遇到它时整个原文被原样返回;随后导入标题的 firstSemanticUserLine() 和列表预览的 waitingSourceText() 都只取到第一行标签。前端即使正确使用预览文本 sourceText,也无法得到后面的用户请求。

建议做法

在共享规则中识别该粘贴来源封装,正确跳过整个封装并提取后面的请求,同时兼容上述闭标签带属性的格式。导入标题、存储层用户首行读取和列表 sourceText 应共用修正后的规则;没有有效请求时按现有约定回退记录 ID,详情继续保留完整原文并安全显示。不要把识别范围扩大为删除任意 HTML、普通引用或代码,也无需批量重写存量摘要。

补充粘贴封装后有请求、只有封装、截断封装、普通正文中出现同名标签的回归,验证导入标题和最终列表显示。相邻格式也应覆盖:[Image] 后接附件与 user_query、chat_selection 来源引用后接请求;它们在等待摘要的格式回放中仍会得到图片标记或代码围栏首行,需同时验证来源格式识别与普通用户代码、引用的保留边界。

PR-725-CR-002-记忆片段.txt

@Orsted290

Copy link
Copy Markdown
Contributor Author

已根据两条 review 意见完成修复,并将本地提交推送到本 PR 分支。新增提交:

  • 1eac16c0 fix: unify trace summaries and source envelope previews
  • 1434a1ba fix: preserve source boundaries and legacy trace bodies

旧 L1 记录标题问题:列表和详情在无有效存储摘要时返回空 summary,不再把正文首行回填成摘要;标题按生成标题、有效摘要、清洗后的 sourceText、记录 ID 回退。日志刷新和详情摘要读取也遵循该约定。隔离 GUI 已分别将无摘要、无生成标题的旧记录置为 ready 和 failed,两种状态均显示清洗后的用户请求;无请求记录回退到 ID。

来源封装与正文展示:补充 pasted_content 等协议封装边界处理;解析时忽略属性、注释中的同名标签,保护真正的对话角色分段。无结构化对话事件的旧记录在详情独立显示完整原文,按纯文本渲染并保留换行。GUI 已验证 Claude Code 的 summary_pending、带属性闭标签的截图格式、属性/注释边界和旧记录正文展示。

验证:针对性回归、全仓测试、类型检查、lint、unsigned arm64 DMG 构建及包内隔离 SQLite 关闭/重开检查均通过;本轮原 Auto-CR 三项复现转绿。此次补验额外完成隔离安装后的列表、详情、搜索、整应用退出重启及数据库逐条核对,截图与日志记录在本地 analysis/pr725-comments-20261027/gui-20261028/。

边界:测试模型仅为本机合成接口,未验证真实模型摘要生成。修复前后的代码/自动化回归对照已有记录,但目前没有可启动的 PR 前桌面包,因此旧版 GUI 前后截图对比仍未验证。应用退出日志出现 quit cleanup timed out; forcing app exit,但进程最终退出且重启后隔离数据完整;该超时原因未归因。

@Orsted290

Copy link
Copy Markdown
Contributor Author

CI 修复补充

根因是 Windows Memory workflow 中 5 个较慢的 runtime installer / Desktop upgrade 测试沿用 Vitest 5 秒默认超时;Windows runner 上实际耗时约 7–13 秒,导致测试超时,后续清理又出现 ENOENT。

已在提交 35201956 为这 5 个测试定义(含参数化用例)设置 20 秒超时。

复验结果:Windows Memory validation、Windows 11 Computer History validation、Linux CLI build 和 x64/arm64 install-smoke 均通过;Linux upload job 按 PR 工作流条件跳过。初次失败的 Windows Memory 检查已由新提交触发并通过。

…memory-titles-v126

# Conflicts:
#	Memory/src/storage/repositories.ts
@origami-chen
origami-chen merged commit 67744eb into MemTensor:v1.2.6 Oct 28, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants