fix(web): summarize session titles, sort by activity, and paginate history (BUG-553)
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -8549,4 +8549,20 @@
|
||||
- 复发自:BUG-329(停止按钮只绑了 `send()` 的 abort,没覆盖选择题与采用)
|
||||
- 修复版本:`055b7adc`
|
||||
|
||||
## BUG-553 | 历史列表只按置顶排,改名收藏后旧会话跳到最顶
|
||||
|
||||
- 状态:resolved
|
||||
- 首次发现:2026-09-06
|
||||
- 最近更新:2026-09-06
|
||||
- 影响面:侧栏历史列表、`GET /api/sessions`、`PATCH /api/sessions/[id]`、`use-session-management`
|
||||
- 用户现象:刚聊过的会话不在最上面;改名、收藏、换模型或换资料后刷新,这条会话反而排到最顶。
|
||||
- 触发条件:登录后打开侧栏历史;对已有会话做元数据 PATCH,或不发新消息就刷新。
|
||||
- 根因:`visibleSessions` 只按 `pinned` 排,开着页面时 `updatedAt` 变化不改位置。元数据 PATCH 和服务端 `metadataUpdateValues` 一律写 `updated_at = now()`,非对话操作也会把会话顶到列表头。真正该 bump 的是发问 / 回答落库。
|
||||
- 修复:`sortSessions` 置顶优先、组内 `updatedAt` 倒序且稳定。元数据 PATCH 不再写 `updated_at`;客户端改名 / 收藏 / 归档 / 换模型 / 换资料不再 `timestamp()`。列表改为游标分页,历史按本地日期分组,侧栏标题去掉资料名前缀。
|
||||
- 验证:`frontend/tests/session-groups.test.ts`、`session-cursor.test.ts`、`chat-session-write.test.ts`(`metadataUpdateValues` 不含 `updated_at`)、`sidebar-state.test.ts`(改名不 bump `updatedAt`)、`sidebar-contract.test.ts`、`chart-library-session.test.ts`。
|
||||
- 防复发:元数据 PATCH 不得写 `updated_at`。`updatedAt` 只由对话活动推进。侧栏历史排序必须置顶 + `updatedAt` 倒序,不得只按置顶。
|
||||
- 相关记录:BUG-024
|
||||
- 复发自:无
|
||||
- 修复版本:待提交
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
# PROGRESS · 历史对话标题、排序、分组与分页(2026-09-06)
|
||||
|
||||
工作树:`.worktrees/session-list-title-and-order-20260906`
|
||||
分支:`codex/session-list-title-and-order-20260906`
|
||||
基线:任务书写 `origin/staging` @ `985c3258`;开工时 `origin/staging` 已到 `d04990fc`(含 composer BUG-551/552),以当时远端为准。
|
||||
|
||||
`page.tsx` 收尾 **2035** 行(上限 2041)。未改迁移、未 bump Skill。5.1 起名走 `generateText` 可 mock;真实模型调用在本机测试里不打外部 API。客户端只引用 `session-title.ts` 纯函数,避免把 Mastra 打进 `/` 包。
|
||||
|
||||
| 任务 | 状态 | BUG |
|
||||
| --- | --- | --- |
|
||||
| 5.2 排序与 `updated_at` | 完成 | BUG-553 |
|
||||
| 5.6 列表游标分页 | 完成 | — |
|
||||
| 5.4 侧栏去资料前缀 | 完成 | — |
|
||||
| 5.3 历史日期分组 | 完成 | — |
|
||||
| 5.1 首轮模型起名 | 完成 | 不编 BUG |
|
||||
| 5.5 BUG_HISTORY / CHANGELOG / DESIGN / VOICE | 完成 | — |
|
||||
|
||||
## 实现要点
|
||||
|
||||
- `sortSessions`:置顶优先,其次 `updatedAt` 倒序,相等保持原序。
|
||||
- 元数据 PATCH 不再写 `updated_at`;客户端改名 / 收藏 / 归档 / 换模型不再 bump。
|
||||
- `GET /api/sessions`:`limit` 默认 40(1–100),`before` 游标 `(updated_at,id)` 倒序,第一页合并全部置顶,后续页只有非置顶;`archived=1` 独立游标。
|
||||
- 历史按本地午夜分成今天 / 昨天 / 最近 7 天 / 最近 30 天 / 更早;空组不渲染。滚到底哨兵静默续取,无「加载更多 / 没有更多」。
|
||||
- 侧栏标题只显示会话标题;`chartProfileRole !== "self"` 时副标题显示资料名(含「资料已删除 · 」)。
|
||||
- 咨询首轮且标题仍是自动值时,与主回答并行起名(8 秒 ref'd 超时,最多 30 token,不扣点)。合格标题经 `session.title` 事件下发,并按「标题仍等于本轮开始值」守卫写库。流结束前会等该事件,避免客户端完成 PATCH 把模型标题盖回去。
|
||||
|
||||
## 既有断言改动
|
||||
|
||||
| 文件 | 原值 | 新值 | 原因 |
|
||||
| --- | --- | --- | --- |
|
||||
| `home-profile.ts` / `chart-library-session` | `资料名 · 标题` | 标题单独一行;他人资料走副标题 | 侧栏前缀把主题挤没 |
|
||||
| `page.tsx` `visibleSessions` | 只按 `pinned` 排 | `sortSessions`(置顶 + `updatedAt` 倒序) | BUG-553:刚聊过的不在最上面 |
|
||||
| `metadataUpdateValues` | 每次 PATCH 写 `updated_at` | 返回值不含 `updated_at` | 改名收藏把旧会话顶上去 |
|
||||
| `renameSession` | `{ ...session, title, updatedAt: timestamp() }` | `{ ...session, title }` | 同上 |
|
||||
| `GET /api/sessions` | 一次返回全部元数据数组 | `{ sessions, nextCursor }`,默认 40 | 上千行 DOM;后续页静默续取 |
|
||||
| `fetchSessions` / hydrate | `readSessions(payload)` | `readSessions(page.sessions)` + `nextCursor` | 分页响应形状 |
|
||||
| `onToggleArchivedView` | 只翻转本地 `showArchivedSessions` | 重新取第一页(`archived=1`) | 归档改由服务端过滤 |
|
||||
| `app-sidebar` 历史区 | `historySessions.map` 一根长列表 | `historyGroups.map` + 哨兵 | 今天 / 昨天 / 更早;无加载文案 |
|
||||
| `use-consultation-run` 完成标题 | `reply.title && !isGenericSessionTitle(reply.title)` | `streamedTitle ?? reply.title` | 首轮模型标题经 `session.title` 事件到达 |
|
||||
| `consult` session select | `...,session_type,messages` | 另加 `title,theme,chart_profile_role` | 起名判定需要当前标题与分析对象 |
|
||||
| `agent.generate` token 上限 | 任务书写 `maxTokens` | `modelSettings.maxOutputTokens` | 当前 Mastra/AI SDK CallSettings 字段名 |
|
||||
|
||||
## 测试
|
||||
|
||||
| 命令 | 结果 |
|
||||
| --- | --- |
|
||||
| `npx tsx --test tests/sidebar-*.test.ts tests/chart-library-session.test.ts tests/chat-session-*.test.ts tests/agent-reply.test.ts tests/consultation-*.test.ts tests/session-*.test.ts tests/application-billing-contract.test.ts` | 355 pass / 0 fail |
|
||||
| `./node_modules/.bin/tsc --noEmit` | 0 错 |
|
||||
| 改动文件 eslint `--quiet` | 0 error |
|
||||
| `page.tsx` | 2035 行(上限 2041) |
|
||||
| `npm run build -- --webpack` | webpack 编译通过;类型检查仍停在既有 `dossierResponse` 路由导出(`api/rectification/cases/[caseId]`),与本单无关。本单曾误把 `metadataUpdateValues` 从 sessions `[id]` 路由再导出,已撤回。 |
|
||||
| 全量 `npm test`(含 `database-*`) | 本机 Docker 库测多项 300s 超时 / 权限负例 ERROR,与本单无关;未当作本单回归。 |
|
||||
@@ -0,0 +1,67 @@
|
||||
# Staging 人肉复核 · 历史对话标题、排序、分组与分页(2026-09-06)
|
||||
|
||||
给产品负责人。不要把真实出生资料、真实用户问题或对话正文写进任何记录。试用问题时用虚构句,例如「半年内换工作时机」。
|
||||
|
||||
对应 BUG-553。测之前先做第 0 条。
|
||||
|
||||
## 0. 确认测的是新版本
|
||||
|
||||
浏览器打开 `https://staging.jyotisha.chat/api/health`,看 `deployment.gitCommit` 前 8 位是否等于本单合入 staging 后的提交。不一致 = 先别测。
|
||||
|
||||
## 1. 新会话首轮标题变成主题总结(P0)
|
||||
|
||||
1. 新建一次普通咨询(不要用生时校正,也不要从今日节奏入口进)。
|
||||
2. 发出一句虚构问题,例如问最近半年换工作的时机。
|
||||
3. 看侧栏这条会话的标题:回答生成期间或结束后。
|
||||
|
||||
- ✅ 预期:标题变成大约 6–12 字的主题,例如「半年内换工作时机」这类总结,而不是第一句话截断加省略号。本人资料时侧栏没有「资料名 · 」前缀。
|
||||
- ❌ 失败:一直停在「新对话」或「我想问一下…」;或标题里出现出生年月日、钟点;或界面出现「正在生成标题」之类提示。
|
||||
|
||||
## 2. 校正和今日节奏标题不变(P0)
|
||||
|
||||
1. 打开生时校正会话。
|
||||
2. 从今日节奏入口开一条会话。
|
||||
|
||||
- ✅ 预期:仍是「M月D日 · 生时校正」或「M月D日 · 今日节奏」,不会被模型改成主题总结。
|
||||
- ❌ 失败:日期式标题被换成别的总结。
|
||||
|
||||
## 3. 改名 / 收藏 / 换模型后刷新不改变顺序(P0)
|
||||
|
||||
1. 找两条未置顶、时间不同的历史会话,记下上下顺序。
|
||||
2. 给下面那条改名、收藏再取消收藏、或换一个模型,然后刷新。
|
||||
|
||||
- ✅ 预期:未置顶时两条的上下顺序不变。收藏后它进「收藏对话」,取消收藏后回到原来的时间位置,不会只因为改名就跳到历史最顶。
|
||||
- ❌ 失败:改个名或换个模型,刷新后这条跑到最上面。
|
||||
|
||||
## 4. 新发一条后该会话到组首(P0)
|
||||
|
||||
1. 对一条未置顶历史会话再发一条虚构问题。
|
||||
2. 看「今天」分组。
|
||||
|
||||
- ✅ 预期:这条出现在「今天」组靠前(置顶仍全体在收藏区)。侧栏分组标签是今天 / 昨天 / 最近 7 天 / 最近 30 天 / 更早,空组没有。
|
||||
- ❌ 失败:发过消息仍停在原地;或出现空的分组标题。
|
||||
|
||||
## 5. 停止回答后标题没有错误提示(P0)
|
||||
|
||||
1. 新会话首轮发出问题后立刻点停止。
|
||||
|
||||
- ✅ 预期:没有红色告警,也没有标题失败提示。标题要么已是总结,要么仍是原来的自动标题。
|
||||
- ❌ 失败:因为起名失败或停止而弹出错误。
|
||||
|
||||
## 6. 超过 40 条时分页(P0)
|
||||
|
||||
账号历史明显超过 40 条时:
|
||||
|
||||
1. 打开未归档历史。
|
||||
2. 滚到列表底部,再往下一点。
|
||||
3. 切到归档视图,同样滚到底。
|
||||
|
||||
- ✅ 预期:首屏大约是最近 40 条非置顶,加上全部收藏。滚到底没有「加载更多」或「没有更多」文案,新行直接接上。归档视图同样分页。
|
||||
- ❌ 失败:一次画出全部历史;或底部出现加载/没有更多字样;或收藏不在第一屏。
|
||||
|
||||
## 7. 他人资料副标题(P1)
|
||||
|
||||
用另一份资料开咨询。
|
||||
|
||||
- ✅ 预期:侧栏主行只有标题;下面一行小字是资料名。资料已删时是「资料已删除 · 资料名」。本人资料没有这行。
|
||||
- ❌ 失败:标题仍是「资料名 · 标题」挤在一行。
|
||||
Reference in New Issue
Block a user