Skip to content

Conversation

@ryanwyler
Copy link
Contributor

Summary

Adds two optional parameters to Session.messages() API for loading messages older than the initial 100-message window:

  • ts_before: Unix timestamp - returns messages created before this point
  • breakpoint: Boolean - when true, stops at the first compaction summary

Problem

Multiple open issues request the ability to access message history beyond the initial 100-message limit:

Current Session.messages() only supports a limit parameter, which returns the N most recent messages. There is no way to retrieve older messages.

Solution

This PR adds the foundational server-side API enhancement required by all proposed solutions. The implementation is minimal (8 lines of core logic) and non-breaking:

Core changes:

  • packages/opencode/src/session/index.ts - Add params to Session.messages() schema and iteration logic
  • packages/opencode/src/server/routes/session.ts - Expose params in HTTP API

Why this approach:

  • Timestamp-based anchoring uses immutable reference points, eliminating state management complexity and race conditions that offset-based pagination would introduce
  • Breakpoint support enables "load conversation history" (stop at compaction) vs "load full session" (ignore compactions) use cases
  • Zero breaking changes - all parameters optional, existing functionality unchanged
  • Prerequisite for all solutions - whether TUI, web client, or SDK consumers implement history loading, they all need this server capability

Usage

# Get messages before a timestamp
GET /session/{id}/message?ts_before=1768609939954

# Get messages before timestamp, stopping at first compaction
GET /session/{id}/message?ts_before=1768609939954&breakpoint=true

# Combine with limit
GET /session/{id}/message?ts_before=1768609939954&limit=50

Testing

Verified against sessions with 170+ messages and multiple compactions:

  • ts_before correctly filters to messages older than timestamp
  • breakpoint=true stops at first compaction part
  • Combined parameters work together
  • Existing behavior unchanged when params omitted

@github-actions
Copy link
Contributor

The following comment was made by an LLM, it may be inaccurate:

Potential Related PRs Found

Here are PRs that may be addressing the same or overlapping issues:

  1. PR feat(tui): load conversation and session history #8627 - feat(tui): load conversation and session history

  2. PR feat(session): bi-directional cursor-based pagination (#6548) #8535 - feat(session): bi-directional cursor-based pagination (#6548)

  3. PR session: paginate message loading #6656 - session: paginate message loading

  4. PR feat(tui): add session_list_limit for session picker (#6137) #6138 - feat(tui): add configurable message_limit for session history (#6137)

Recommendation: Check PR #8535 most carefully, as it addresses the same root issue (#6548) but with a different pagination strategy. Clarify whether the timestamp-based approach in the current PR is preferred, or if both should coexist.

@ryanwyler
Copy link
Contributor Author

Analysis of Related PRs

I've reviewed all potentially related PRs to clarify how this PR fits into the broader solution space.


PR #8535 - "bi-directional cursor-based pagination"

Status: Open | Additions: 1,228 lines | Approach: Cursor-based with RFC 5005 Link headers

This is the most comprehensive competing approach. Key differences:

Aspect This PR (#8996) PR #8535
Core logic 8 lines ~200+ lines
Parameters ts_before, breakpoint before, after, oldest + Link headers
Scope Server API only Server + TUI + tests
Compaction awareness Yes (breakpoint) No
Complexity Minimal Significant (memory bounding, sliding window, RFC compliance)

Why this PR should still be considered:

  1. Simplicity - Timestamp-based anchoring is fundamentally simpler than cursor management. Timestamps are immutable; cursors require state tracking.

  2. Compaction-aware loading - The breakpoint parameter enables "load to last context boundary" which is semantically meaningful for LLM conversations. PR feat(session): bi-directional cursor-based pagination (#6548) #8535 doesn't address compaction boundaries.

  3. Incremental adoption - This PR can merge independently and immediately benefit SDK consumers, web clients, and alternative TUI implementations without waiting for the full pagination system.

  4. Not mutually exclusive - These approaches could coexist. ts_before provides simple temporal queries; cursor-based pagination provides full bidirectional navigation with Link headers.


PR #6656 - "paginate message loading"

Status: Open | Additions: 200 lines

An earlier partial implementation that PR #8535 explicitly supersedes. Uses before cursor but lacks:

  • Bidirectional support
  • Memory bounding
  • Proper Link header parsing

Verdict: Superseded by #8535. Not relevant to this PR's approach.


PR #6138 - "configurable message_limit"

Status: Open | Additions: 20 lines | Approach: Config-based limit increase

Simply allows users to configure a higher limit (e.g., 500 instead of 100).

Why this doesn't solve the problem:

  • Still loads all messages upfront (memory/performance issue at scale)
  • No way to load older messages on-demand
  • Doesn't address the fundamental "can't access old messages" issue

Verdict: Complementary but insufficient. Users with 1000+ message sessions still can't access early history.


PR #8627 - "load conversation and session history" (original full implementation)

Status: Open (conflicts) | Additions: 176 lines

This is the same author's complete implementation that includes:

Relationship to this PR: This PR (#8996) extracts just the server-side foundation from #8627, allowing:

  1. The API enhancement to merge independently
  2. TUI implementation to be reviewed separately
  3. Other clients (web, SDK consumers) to benefit immediately

Recommendation

This PR should merge because:

  1. Minimal risk - 8 lines of additive, non-breaking logic
  2. Immediate value - Unblocks multiple consumers (TUI PR feat(tui): load conversation and session history #8627, web client, SDK users)
  3. Unique capability - breakpoint parameter for compaction-aware loading isn't in any other PR
  4. Complements rather than conflicts - Can coexist with cursor-based pagination if feat(session): bi-directional cursor-based pagination (#6548) #8535 also merges

The choice between timestamp-based (#8996) and cursor-based (#8535) pagination isn't either/or - they serve different use cases. Timestamps are ideal for "load everything before X" queries; cursors are ideal for "give me the next/previous page" navigation.

@ryanwyler ryanwyler force-pushed the feature/load-additional-session-messages branch from e086d9d to e55fcdf Compare January 17, 2026 00:44
ryanwyler added a commit to gignit/opencode that referenced this pull request Jan 17, 2026
Adds UI for loading older messages in long-running sessions:
- 'Load more messages' banner appears when 100+ messages present
- Two loading modes: conversation history (stops at compaction) and full session
- Toast notifications show count of messages loaded

Depends on: PR anomalyco#8996 (ts_before and breakpoint API params)
ryanwyler added a commit to gignit/opencode that referenced this pull request Jan 17, 2026
Adds UI for loading older messages in long-running sessions:
- 'Load more messages' banner appears when 100+ messages present
- Two loading modes: conversation history (stops at compaction) and full session
- Toast notifications show count of messages loaded

Depends on: PR anomalyco#8996 (ts_before and breakpoint API params)
@ryanwyler ryanwyler force-pushed the feature/load-additional-session-messages branch from e55fcdf to 85a0f58 Compare January 17, 2026 03:58
…s API

Add optional parameters to Session.messages() for loading older messages:
- ts_before: filter to messages created before this timestamp
- breakpoint: stop at first compaction summary when true

This is a foundational API enhancement that enables clients to implement
pagination and history loading without breaking existing functionality.
@ryanwyler ryanwyler force-pushed the feature/load-additional-session-messages branch from 85a0f58 to a44b069 Compare January 17, 2026 04:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant