Skip to content

fix(web): preserve loaded history during streaming - #1126

Open
GoldenZqqq wants to merge 2 commits into
tiann:mainfrom
GoldenZqqq:fix/web-preserve-history-while-streaming
Open

fix(web): preserve loaded history during streaming#1126
GoldenZqqq wants to merge 2 commits into
tiann:mainfrom
GoldenZqqq:fix/web-preserve-history-while-streaming

Conversation

@GoldenZqqq

Copy link
Copy Markdown
Contributor

Summary

When the user is not at the bottom, streaming agent messages went through ingestIncomingMessages and were immediately front-trimmed to the normal visible window (~400). An expanded older-history window (~800 after Load older) could therefore lose the older page as soon as the agent streamed more output, so Load older looked broken or had to be repeated.

Changes:

  1. Above-bottom agent merges no longer trim; they only merge into the current window.
  2. setAtBottom(true) compacts back to the normal window when the user returns to the bottom.

Test plan

  • cd web && bunx vitest run src/lib/message-window-store.test.ts (23 passed), including new case keeps loaded history while agent output streams above the bottom
  • Manual: load older in a long session, stay scrolled up while the agent streams; older messages remain
  • Manual: scroll back to bottom; window trims to the recent visible range and hasMore stays correct

Fixes #1071

Himehane and others added 2 commits July 22, 2026 17:20
修复 Codex 会话导入合并后列表为空的问题。

Fix Codex session import merge so a session is not detected as a duplicate of itself and deleted during merge.

Co-authored-by: LIUZHIRU <ryuu@fine-net.co.jp>
When the user is reading above the bottom, merge streaming agent
messages without front-trimming the visible window so an expanded
older-history page is not discarded mid-stream. Compact back to the
normal window only when setAtBottom(true) runs.

Fixes tiann#1071

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Findings

  • [Major] Scrolled-up streaming window is now unbounded — why it matters: while the user is reading older history, every agent SSE merge appends into messages without any trim. This store feeds SessionChat/HappyThread directly, so a long-running stream can keep growing the rendered thread until the user returns to the bottom. The previous code kept the live window bounded; this PR should preserve the loaded older page without removing the cap entirely. Evidence web/src/lib/message-window-store.ts:1041.
    Suggested fix:
    const messages = mergeMessages(state.messages, agentMessages)
    const { kept, dropped } = trimPreservingQueued(
        messages,
        OLDER_LOAD_WINDOW_SIZE + VISIBLE_WINDOW_SIZE,
        'append'
    )
    const pending = filterPendingAgainstVisible(state.pending, kept)
    state = buildState(state, {
        messages: kept,
        pending,
        ...cursorUpdatesAfterAppendTrim(kept, dropped)
    })

Summary

  • Review mode: initial
  • One major issue found: above-bottom streaming now has no bounded window. Residual risk: the new test covers one streamed message, but not a long stream past the expanded-window budget.

Testing

  • Not run (automation)

HAPI Bot

// Streaming agent events are frequent; trimming from the front on every
// event used to evict the older page that had just been loaded, making the
// user repeatedly click "Load older". Compact once they return to bottom.
const messages = mergeMessages(state.messages, agentMessages)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[MAJOR] Scrolled-up streaming now appends into messages without any cap. Because this store feeds the chat thread directly, a long-running agent stream while the user is reading older history can keep growing the rendered thread until they return to the bottom. Preserve the loaded older page, but keep a bounded scrolled-up window.

Suggested fix:

const messages = mergeMessages(state.messages, agentMessages)
const { kept, dropped } = trimPreservingQueued(
    messages,
    OLDER_LOAD_WINDOW_SIZE + VISIBLE_WINDOW_SIZE,
    'append'
)
const pending = filterPendingAgainstVisible(state.pending, kept)
state = buildState(state, {
    messages: kept,
    pending,
    ...cursorUpdatesAfterAppendTrim(kept, dropped)
})

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Streaming can discard explicitly loaded older history

2 participants