Repository navigation
修复 Agent 扫描记忆标题及详情页用户内容展示 - #725
origami-chen merged 7 commits into
Conversation
| return summary; | ||
| if (item.kind === "trace") { | ||
| // All processing states use the read model preview, never raw source text. | ||
| return summary ?? waitingPrimaryText(item); |
There was a problem hiding this comment.
旧记录没有摘要时,原文标签仍会盖过已清洗的用户请求
问题
打开一条尚无有效摘要、也没有生成标题的旧版 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 调用方。改动限定在此次原始对话摘要回退问题,保留聚合记忆、工作记忆等其它类型的原有字段含义。
|
|
||
| // 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; |
There was a problem hiding this comment.
问题**
查看尚在等待摘要的 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 来源引用后接请求;它们在等待摘要的格式回放中仍会得到图片标记或代码围栏首行,需同时验证来源格式识别与普通用户代码、引用的保留边界。
|
已根据两条 review 意见完成修复,并将本地提交推送到本 PR 分支。新增提交:
旧 L1 记录标题问题:列表和详情在无有效存储摘要时返回空 summary,不再把正文首行回填成摘要;标题按生成标题、有效摘要、清洗后的 sourceText、记录 ID 回退。日志刷新和详情摘要读取也遵循该约定。隔离 GUI 已分别将无摘要、无生成标题的旧记录置为 来源封装与正文展示:补充 验证:针对性回归、全仓测试、类型检查、lint、unsigned arm64 DMG 构建及包内隔离 SQLite 关闭/重开检查均通过;本轮原 Auto-CR 三项复现转绿。此次补验额外完成隔离安装后的列表、详情、搜索、整应用退出重启及数据库逐条核对,截图与日志记录在本地 边界:测试模型仅为本机合成接口,未验证真实模型摘要生成。修复前后的代码/自动化回归对照已有记录,但目前没有可启动的 PR 前桌面包,因此旧版 GUI 前后截图对比仍未验证。应用退出日志出现 |
CI 修复补充根因是 Windows Memory workflow 中 5 个较慢的 runtime installer / Desktop upgrade 测试沿用 Vitest 5 秒默认超时;Windows runner 上实际耗时约 7–13 秒,导致测试超时,后续清理又出现 ENOENT。 已在提交 复验结果:Windows Memory validation、Windows 11 Computer History validation、Linux CLI build 和 x64/arm64 install-smoke 均通过;Linux |
…memory-titles-v126 # Conflicts: # Memory/src/storage/repositories.ts
问题定位
Agent 扫描记忆时,用户消息开头可能带有时间戳、浏览器上下文、技能或附件等来源信息,导致列表标题重复显示标签;摘要失败或为空时,回退正文也可能重新泄漏这些内容。部分带来源封装的记录在详情页无法正确显示“用户”内容。
修改内容
测试结果
范围说明
本 PR 只包含标题提取、详情页用户内容展示及对应回归测试;不包含历史 Codex 自动审查记录的批量清理。