#17776 · @BYK · opened Mar 16, 2026 at 10:27 AM UTC · last updated Mar 21, 2026 at 10:24 AM UTC

fix(app): cap force-refresh limit to page size on session switch

appfix
69
+744 files

Score breakdown

Impact

9.0

Clarity

9.0

Urgency

8.0

Ease Of Review

9.0

Guidelines

7.0

Readiness

9.0

Size

10.0

Trust

5.0

Traction

0.0

Summary

This PR addresses a performance regression where session switching became progressively slower due to an inflated message limit being reused on force-refresh. It caps the limit to the page size during force-refreshes, resolving a significant user experience issue. The fix is well-explained with strong verification steps, but includes minor unrelated changes.

Open in GitHub

Description

Issue for this PR

Closes #17775

Type of change

  • [x] Bug fix
  • [ ] New feature
  • [ ] Refactor / code improvement
  • [ ] Documentation

What does this PR do?

meta.limit in sync.tsx grows monotonically via loadMore() as the user scrolls up through message history (200 → 400 → 600 → ...). When switching sessions and returning after the 15s prefetch TTL, a force-refresh reuses this inflated limit — re-downloading the entire browsing history from scratch on every session switch.

This caps the limit to messagePageSize (200) on force-refreshes:

// Before:
const limit = meta.limit[key] ?? messagePageSize

// After:
const limit = opts?.force ? messagePageSize : (meta.limit[key] ?? messagePageSize)

After the force-refresh, loadMessages() resets meta.limit and meta.cursor to match the fresh page, so loadMore() continues to work normally for scrolling up through older history.

How did you verify your code works?

  • Opened a long session, scrolled up several times to grow meta.limit
  • Switched away, waited 15s, switched back
  • Verified force-refresh only fetches 200 messages (not the full history)
  • Verified scrolling up still loads older pages via loadMore()

Screenshots / recordings

N/A — behavioral fix in pagination logic.

Checklist

  • [x] I have tested my changes locally
  • [x] I have not included unrelated changes in this PR

Linked Issues

#17775 Session switching gets progressively slower as message history grows

View issue

Comments

No comments.

Changed Files

packages/app/src/components/dialog-connect-provider.tsx

+11
@@ -383,7 +383,7 @@ export function DialogConnectProvider(props: { provider: string }) {
setFormStore("error", undefined)
await globalSDK.client.auth.set({
providerID: props.provider,
auth: {
body: {
type: "api",
key: apiKey,
},

packages/app/src/components/dialog-custom-provider.tsx

+11
@@ -131,7 +131,7 @@ export function DialogCustomProvider(props: Props) {
const auth = result.key
? globalSDK.client.auth.set({
providerID: result.providerID,
auth: {
body: {
type: "api",
key: result.key,
},

packages/app/src/context/sync.tsx

+41
@@ -460,7 +460,10 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
const cached = store.message[sessionID] !== undefined && meta.limit[key] !== undefined
if (cached && hasSession && !opts?.force) return
const limit = meta.limit[key] ?? messagePageSize
// Force-refreshes fetch the latest page, not the entire browsing
// history. meta.limit grows via loadMore() as the user scrolls up
// and that inflated value must not carry into a fresh re-fetch.
const limit = opts?.force ? messagePageSize : (meta.limit[key] ?? messagePageSize)
const sessionReq =
hasSession && !opts?.force
? Promise.resolve()

packages/opencode/src/cli/cmd/tui/component/dialog-provider.tsx

+11
@@ -265,7 +265,7 @@ function ApiMethod(props: ApiMethodProps) {
if (!value) return
await sdk.client.auth.set({
providerID: props.providerID,
auth: {
body: {
type: "api",
key: value,
},