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-orig 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-orig 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.
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