[PR #8627] feat(tui): load conversation and session history #12812

Closed
opened 2026-02-16 18:17:42 -05:00 by yindo · 0 comments
Owner

Original Pull Request: https://github.com/anomalyco/opencode/pull/8627

State: closed
Merged: No


Resolves #6137, #4918, #7380
Related to #6548

Problem

Users cannot access message history beyond the initial 100 messages loaded on session init. This makes OpenCode history for long-running sessions incomplete:

  • Users need to reference earlier context (issue #7380)
  • Sessions span hundreds of interactions (issue #4918)
  • Important information from early messages becomes inaccessible (issue #6137)

Solution

This solution does not disrupt the natural 100 message limit for the TUI client maintaining the current message roll-off strategy in place.

Functional Core: ~38 lines (22% of changes)

  • Server logic: 18 lines
  • Client logic: 20 lines The rest is either:
  • UI presentation (buttons, colors, hover states)
  • Auto-generated SDK types (non-disruptive additional options for Session.messages())
  • Comments and structure

Elegant, non-disruptive implementation that adds on-demand message loading with two modes accessed via a "Load more messages" UI when 100+ messages are present:

  1. Load conversation history - Loads messages up to the next compaction summary, providing relevant context without overwhelming the UI
  2. Load full session history - Loads all remaining messages for complete session reconstruction

Only pulls the missing messages - does not reload the entire session, only the missing messages due to the ts_before implementation.

Zero breaking changes - All parameters optional, existing functionality completely unchanged.

Message roll-off maintained - There is a system in the client today that once the messages reach over 100 messages, one message is rolled-off with each new message. This roll-off strategy works perfectly with this feature. A user can load their conversation or their session history and continue their session and the last message will roll off as a new message comes in. If for some reason the user wants to bring back the earliest messages again, they can click the load button at the top to load them all back in, but this natural pruning system is important to maintain and this solution fits perfectly with the entire existing system.

Implementation

Uses timestamp-based anchoring (immutable reference points) rather than offset/count tracking, eliminating state management complexity and race conditions.

Server API Enhancement - Added optional parameters to Session.messages():

  • ts_before: Unix timestamp for loading messages older than a specific point
  • breakpoint: Boolean controlling whether to stop at compaction summaries

This enhances the robustness of the server messaging system by providing precise temporal queries rather than simple limits. The ts_before parameter acts as an immutable anchor point that naturally handles concurrent updates and message insertion without index drift.

Client - Two load functions that prepend older messages to the existing array, maintaining chronological order. Toast notifications show message counts.

Total addition: 176 lines across 7 files

Technical Details

  • Server logic handles reverse iteration with optional breakpoint stopping
  • Client omits breakpoint parameter for full history (undefined = falsy)
  • Uses z.coerce.boolean() pattern consistent with other boolean parameters like roots
  • Timestamps are immutable - no race conditions or state tracking needed

Testing

Verified with sessions containing 1000+ messages:

  • Conversation history stops at compaction summaries
  • Full session history loads all remaining messages
  • Accurate message counts in toast notifications
  • No disruption to real-time message updates

Additional Consideration

The server Session.messages() enhancement with ts_before & breakpoint would greatly benefit the web client implementation, which currently reloads all messages when loading more. The timestamp-based approach would allow incremental loading without re-fetching existing messages.

Screenshots

Option to load conversation (next breakpoint) or full session (all breakpoints)
image

Loading conversation history
image

Loading full session history
image

**Original Pull Request:** https://github.com/anomalyco/opencode/pull/8627 **State:** closed **Merged:** No --- Resolves #6137, #4918, #7380 Related to #6548 ## Problem Users cannot access message history beyond the initial 100 messages loaded on session init. This makes OpenCode history for long-running sessions incomplete: - Users need to reference earlier context (issue #7380) - Sessions span hundreds of interactions (issue #4918) - Important information from early messages becomes inaccessible (issue #6137) ## Solution > This solution does not disrupt the natural 100 message limit for the TUI client maintaining the current message roll-off strategy in place. Functional Core: ~38 lines (22% of changes) - Server logic: 18 lines - Client logic: 20 lines The rest is either: - UI presentation (buttons, colors, hover states) - Auto-generated SDK types (non-disruptive additional options for Session.messages()) - Comments and structure **Elegant, non-disruptive implementation** that adds on-demand message loading with two modes accessed via a "Load more messages" UI when 100+ messages are present: 1. **Load conversation history** - Loads messages up to the next compaction summary, providing relevant context without overwhelming the UI 2. **Load full session history** - Loads all remaining messages for complete session reconstruction **Only pulls the missing messages** - does not reload the entire session, only the missing messages due to the `ts_before` implementation. **Zero breaking changes** - All parameters optional, existing functionality completely unchanged. **Message roll-off maintained** - There is a system in the client today that once the messages reach over 100 messages, one message is rolled-off with each new message. This roll-off strategy works perfectly with this feature. A user can load their conversation or their session history and continue their session and the last message will roll off as a new message comes in. If for some reason the user wants to bring back the earliest messages again, they can click the load button at the top to load them all back in, but this natural pruning system is important to maintain and this solution fits perfectly with the entire existing system. ## Implementation Uses timestamp-based anchoring (immutable reference points) rather than offset/count tracking, eliminating state management complexity and race conditions. **Server API Enhancement** - Added optional parameters to `Session.messages()`: - `ts_before`: Unix timestamp for loading messages older than a specific point - `breakpoint`: Boolean controlling whether to stop at compaction summaries This enhances the robustness of the server messaging system by providing precise temporal queries rather than simple limits. The `ts_before` parameter acts as an immutable anchor point that naturally handles concurrent updates and message insertion without index drift. **Client** - Two load functions that prepend older messages to the existing array, maintaining chronological order. Toast notifications show message counts. Total addition: 176 lines across 7 files ## Technical Details - Server logic handles reverse iteration with optional breakpoint stopping - Client omits `breakpoint` parameter for full history (undefined = falsy) - Uses `z.coerce.boolean()` pattern consistent with other boolean parameters like `roots` - Timestamps are immutable - no race conditions or state tracking needed ## Testing Verified with sessions containing 1000+ messages: - Conversation history stops at compaction summaries ✅ - Full session history loads all remaining messages ✅ - Accurate message counts in toast notifications ✅ - No disruption to real-time message updates ✅ ## Additional Consideration The server Session.messages() enhancement with ts_before & breakpoint would greatly benefit the web client implementation, which currently reloads all messages when loading more. The timestamp-based approach would allow incremental loading without re-fetching existing messages. ## Screenshots Option to load conversation (next breakpoint) or full session (all breakpoints) <img width="1640" height="1034" alt="image" src="https://github.com/user-attachments/assets/4adc651d-234e-4c86-b053-b915f8ad4e13" /> Loading conversation history <img width="1640" height="1034" alt="image" src="https://github.com/user-attachments/assets/0295acd6-4f65-4e0f-b3e2-138c78eee2a2" /> Loading full session history <img width="1640" height="1034" alt="image" src="https://github.com/user-attachments/assets/d1cc2074-724d-4edf-8dc0-e1bbd5dbdcb7" />
yindo added the pull-request label 2026-02-16 18:17:42 -05:00
yindo closed this issue 2026-02-16 18:17:42 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: anomalyco/opencode#12812