Skip to main content

page

Function page 

Source
pub fn page(
    messages: &[Message],
    rendered: &Rendered,
    dropped: usize,
    dropped_thinking: i64,
    before: Option<&str>,
    turns: u32,
) -> Page
Expand description

Slice a conversation into whole turns, newest first.

The fold is what says where a turn begins - the span render reports, in message terms. Slicing on a count of messages instead would cut a turn in half, which is the breakage the design exists to avoid.

The cursor errs toward OVERLAP, never toward a gap. A client asking for more may be handed a turn it already has - it keys its turns and drops the repeats - but never a HOLE, which is history it has no way to ask for again.

The cursor is a POSITION, not a name, and the reason is a fact about the read rather than a preference. A turn’s name is its key, and the fold builds one only from a Message::Result frame - while a conversation read from a transcript carries none: SessionMessageKind is User | Assistant | System with no Result kind, and the replay synthesizer never emits one. So a keyed cursor is None on every page of every transcript-derived conversation, and a client reading None as “nothing above” stops after the first page. The message the page’s first turn opens at is the one thing that always names it.

dropped is how many messages the held conversation has lost off the front, and it is what makes that position survive a drop: the held list is renumbered by one and the conversation is not, so a page carries the conversation’s numbering and this is the offset between the two.