Files
orca/src/shared/structured-agent-session-reconnect.ts
T
Brennan Benson c88e9d7054 fix(mobile): reopen the phone chat's live feed from its last row when it ends (#29007)
* fix(mobile): reopen the phone chat's live feed from its last row when it ends

The phone opened a chat's live transcript stream once per connection and never reopened it when the
stream ended or failed while the connection stayed up, so the chat silently froze on old rows. Move
desktop's reopen-from-cursor read into src/shared and run the phone on it too, with an app-foreground
retry.

* fix(mobile): retry the chat feed on the app-resume signal client-context already relays

Module mocking react-native in the shared vitest setup is rejected; publish the existing revival
nudge instead, the way desktop's host-contact signal feeds its read.

* test(mobile): let the phone's coalesced live read apply each frame before comparing
2026-10-20 11:43:42 -07:00

49 lines
1.2 KiB
TypeScript

const RECONNECT_FIRST_DELAY_MS = 750
const RECONNECT_MAX_DELAY_MS = 30_000
/** Each reconnect waits twice the last, up to the cap, until a read delivers. */
export function createReconnectScheduler(args: {
shouldStop: () => boolean
reconnect: () => void
}) {
let timer: ReturnType<typeof setTimeout> | null = null
let nextDelay = RECONNECT_FIRST_DELAY_MS
return {
schedule(): void {
if (args.shouldStop() || timer) {
return
}
const delay = nextDelay
nextDelay = Math.min(delay * 2, RECONNECT_MAX_DELAY_MS)
timer = setTimeout(() => {
timer = null
if (!args.shouldStop()) {
args.reconnect()
}
}, delay)
},
/** A read delivered, so the next failure is retried soon again. */
reset(): void {
nextDelay = RECONNECT_FIRST_DELAY_MS
},
/** The host is reachable again: a waiting retry runs now instead of after the grown wait. */
retryNow(): void {
nextDelay = RECONNECT_FIRST_DELAY_MS
if (!timer) {
return
}
clearTimeout(timer)
timer = null
if (!args.shouldStop()) {
args.reconnect()
}
},
dispose(): void {
if (timer) {
clearTimeout(timer)
timer = null
}
}
}
}