### What happened? / 问题描述 会话列表里同一会话出现两次,两条标题几乎一样(本机实测其中一条标题多了一个「pi」字样),共发现 5 组重复。用户无法分辨哪条是正身,容易点错会话,也不敢删除。 ### Steps to reproduce / 复现步骤 1. 在会话扫描根的任意子目录里放一份现有会话 `.jsonl` 的副本(备份、手工拷贝都会触发) 2. 重启应用(或刷新会话列表) 3. 该会话在列表里出现两条 ### Expected behavior / 预期行为 会话身份应由会话头里的 id(`header.id`)决定,而不是文件路径:同一 nativeId 的多个路径应合并为一条(例如取 mtime 最新的路径),至少应在列表层去重。 ### Actual behavior / 实际行为 每个路径都成为一条独立会话。 ### 根因 / Root cause `packages/agent-runtime/src/native-pi-session.ts`: - `walkJsonl()`(约 L180)递归收集扫描根下**所有子目录**中的 `*.jsonl`; - `list()` 中每个文件的会话 ID 为 `stableId(path, header.id)`(约 L508),**文件路径参与哈希**。 于是同一份会话文件(同一 `header.id`)只要在扫描根下存在第二个路径,就会生成第二个 ID、显示为第二条会话。扫描只排除了符号链接(`lstatSync(path).isSymbolicLink()`),不识别内容副本。 ### App version / 应用版本 0.16.0(当前 main 分支代码仍如此) ### OS Windows
Activity
yexisu commentedon Oct 4, 2026
已提 PR:#1368(基于最新 main
c79b6ca56)。修复与你定位的根因一致:
stableId(path, header.id)把路径掺进会话身份哈希,而walkJsonl()递归收集扫描根下所有.jsonl,副本文件必然生成第二个 ID。PR 在list()扫描完成后按 native header id 去重——同一 nativeId 保留updatedAt最新的路径,并把过期副本从records映射中清除,避免 detail/search/prompt 查找路由到死副本。有意未改动
stableId本身:路径继续参与哈希,已持久化的会话 ID 引用全部保持有效,只移除列表层的重复项。去重仅在扫描结果上做,无额外 I/O。验证:
native-pi-session.test.ts36/37(新增回归:子目录备份副本折叠为原 ID;唯一失败项 "never deletes a foreign publication" 在干净 main 上同样复现,属既有基线噪音)。fix(sessions): collapse copied session files onto one entry per nativ…
test(sessions): pin the canonical file in the copy dedupe