perf(desktop): transcript tail hydration — 120-row tail page + on-demand older-page backfill - #87533
Merged
Merged
Conversation
… older-page backfill Replace the fixed 500-message REST hydration (getLatestSessionMessages) with a 120-row newest-first tail page. When the page comes back full, a new per-session tail store records "possibly truncated + next offset"; "Show earlier" — once the DOM budget and the in-memory store window are both exhausted — fetches the next older page via the new getOlderSessionMessages helper (order latest + offset, matching the backend's back-from-newest paging semantics) and prepends it to the session store, deduped by durable row id and race-guarded against session switches. Legacy backends without pagination metadata fall back to the one-shot full transcript and retire the action. Tail-page refreshes (background sync, post-turn rehydrate, re-activate, cold-resume prefetch) graft the refreshed tail onto any backfilled prefix instead of clobbering it, preserving reference identity on no-ops. includeCompacted stays on every read — compaction-archived rows remain part of the durable display history.
Contributor
૮ >ﻌ< ა ci reviewran on 9c33c20 — perf(desktop): hydrate transcripts with a small tail page +
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Desktop hydrated every session transcript with a fixed
limit: 500REST read (getLatestSessionMessages), shipping and converting up to 500 rows on every session open, background-sync refresh, post-turn rehydrate, and tile resume — regardless of what the transcript window would ever paint.This PR replaces that with a small tail page plus on-demand older-page backfill:
getLatestSessionMessagesnow requestslimit: 120, order: 'latest', include_compacted: true(theincludeCompactedflag is load-bearing for compaction-archived rows and is kept on every read). A new exported constantLATEST_SESSION_MESSAGES_LIMITpins the page size.getOlderSessionMessages(id, profile, offset, limit=120)pages backwards from the newest message. Verified againstgateway/platforms/api_server.py::_handle_session_messages→SessionDB.get_messages(latest=True): withorder: 'latest',offsetis measured back from the newest row and each page returns in chronological order — so after N tail rows,offset=Nis exactly the next older page.store/transcript-tail.tsrecords per stored-session id whether the hydration page came back full (returned === limit⇒ older rows likely exist) and the next offset, plus the owning profile so backfill routes to the same backend.Show earlierbackfill (app/chat/transcript-backfill.ts+ChatRuntimeBoundaryinapp/chat/index.tsx): the action still spends the DOM budget first, then the in-memory store window; once the whole in-memory transcript is materialized (windowedfalse) and the tail bookkeeping says truncated, it fetches the next older page and PREPENDS it to the session store via the session-state write path (sessionTileDelegate().updateSession). Prepends dedupe by durable row id (fallback: rendered message id), preserve reference identity on no-ops, share one in-flight fetch per stored session, and discard stale responses after a session switch (same shape as theisCurrentResume()guards inuse-session-actions).paginationmetadata) returns the full transcript one-shot; the merge prepends the missing prefix and the bookkeeping marks the session fully loaded, retiring the REST action.reconcileActiveTranscript), the post-turn rehydrate (wiring.tsx), warm re-activate, and the cold-resume prefetch now graft the refreshed newest-tail page onto any already-backfilled older prefix (graftRefreshedTailOntoBackfill) instead of clobbering it. When no anchor is found (compaction rewrite / different session) the refreshed tail stays authoritative — identical to pre-change behavior. The empty-REST-page reconciliation guard inuse-session-actions(~L889) is untouched and still short-circuits before any graft.use-background-syncanduse-session-tile-delegateonly ever needed the tail; they simply get the smaller page.Request shape, before → after
Validation
npx vitest runon the six touched suites (hermes.test.ts,transcript-backfill.test.ts,transcript-window.test.ts,use-session-actions.test.tsx,use-background-sync.test.ts,use-session-tile-delegate.test.ts): 7 files, 131 tests, all passing. New tests cover: (a) initial hydration requests limit 120 withorder=latest&include_compacted=true; (b) backfill prepends the older page, dedupes by row id, preserves chronological order and reference identity; (c) a legacy response without pagination metadata falls back to the one-shot full transcript and retires the action; (d) a stale backfill response after a session switch is discarded with bookkeeping untouched.npm run check:lintinapps/desktop(tsc on all three tsconfigs + eslint): 0 errors (pre-existing warnings only).Related
Infographic