Skip to content

Bug: 多次切换 session 后消息顺序错乱 #148

@0x7551

Description

@0x7551

Bug: 多次切换 session 后消息顺序错乱

问题概述

在 Web UI 中多次切换 session 后,消息顺序会出现错乱。命令执行卡片堆积在底部,而新消息(包括授权提示)出现在上方,需要向上滚动才能看到最新内容。

复现步骤

  1. 在 Web UI 中打开一个有消息的 session
  2. 切换到另一个 session
  3. 切换回原来的 session
  4. 重复步骤 2-3 多次
  5. 观察消息顺序是否错乱

期望行为

无论用户切换 session 多少次,消息应始终按时间顺序显示(旧消息在上,新消息在下)。

实际行为

  1. 消息顺序错乱:多次切换 session 后,消息顺序变乱。命令执行卡片(tool calls)堆积在底部,而新消息出现在上方。

  2. 新消息需要手动导航:当消息顺序错乱后继续对话:

    • 会出现"新消息 ↓"提示
    • 点击后滚动到底部
    • 但实际的新消息/授权提示在堆积的命令卡片上方
    • 用户需要向上滚动才能看到和操作新内容
  3. 不稳定复现:触发后不是每次打开都是乱的,在同一个会话中多对话几次有概率恢复正常。

环境

  • 平台:Web(移动端浏览器)
  • 多个 session 都可能受影响

技术分析(待验证)

数据库验证

初步检查了受影响的 session:

  • seq 值连续(1, 2, 3, ... N)无跳跃
  • seqcreated_at 时间戳一致(seq 大的 created_at 也大)
  • 所有消息 isSidechain = false

注意:以上结论需要进一步验证,尚未逐条对照消息确认。

可能的根因

web/src/lib/messages.ts 中的 compareMessages 函数可能存在排序逻辑问题:

function compareMessages(a: DecryptedMessage, b: DecryptedMessage): number {
    const aSeq = typeof a.seq === 'number' ? a.seq : null
    const bSeq = typeof b.seq === 'number' ? b.seq : null
    if (aSeq !== null && bSeq !== null && aSeq !== bSeq) {
        return aSeq - bSeq  // 按 seq 排序
    }
    if (a.createdAt !== b.createdAt) {
        return a.createdAt - b.createdAt  // 按 createdAt 排序
    }
    return a.id.localeCompare(b.id)  // 按 UUID 字典序排序
}

可能的问题 1:当一条消息有 seq 而另一条没有时(乐观消息的 seq: null),函数会直接比较 createdAt,可能导致乐观消息相对于服务器确认的消息位置不正确。

可能的问题 2:当 createdAt 值相同(同一毫秒内)时,函数使用 id.localeCompare() 排序。UUID 的字典序与 seq 顺序不一致,可能导致排序错误。

后续计划

我会尝试自己调试和修复这个问题:

  • 稳定复现问题
  • 使用浏览器开发者工具调试,确认前端消息的实际 seq 和 createdAt 值
  • 确认根因后提交 PR 修复

相关 Issue

其他

滚动被强制拉回底部的问题也有报告,但无法稳定复现,暂不包含在此 issue 中。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions