Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,10 @@ export const useSessionHydration = ({
}
}
}
timer = setTimeout(poll, delay)
// First tick fires NOW, not after REMOTE_RUN_POLL_MS: most turns finish inside 15s, and a
// pending first tick is discarded by the cleanup below when the run ends — so a delayed
// first tick meant short runs were often never fetched at all (#5624).
void poll()
return () => {
cancelled = true
if (timer) clearTimeout(timer)
Expand All @@ -243,5 +246,25 @@ export const useSessionHydration = ({
// above, so a re-render can't cancel a pending tick or reset the backoff.
}, [runningElsewhere, sessionId])

// One final catch-up on the falling edge (#5624). The poll above dies with `runningElsewhere`,
// discarding any pending tick, so a run that ends between ticks would leave the last records
// unfetched until a remount. Guarded adoption makes a spurious extra read harmless.
const prevRemoteRunRef = useRef({sessionId, running: false})
useEffect(() => {
const prev = prevRemoteRunRef.current
prevRemoteRunRef.current = {sessionId, running: runningElsewhere}
if (prev.sessionId !== sessionId || !prev.running || runningElsewhere) return
let cancelled = false
const adopt = adoptServerTranscriptRef.current
loadSessionMessages(sessionId, (fresh) => {
if (!cancelled) adopt(fresh, {armJump: false})
}).then((transcript) => {
if (!cancelled) adopt(transcript, {armJump: false})
})
return () => {
cancelled = true
}
}, [runningElsewhere, sessionId])

return {isHydrating, hydratedEmpty, runningElsewhere}
}
Loading