-
Notifications
You must be signed in to change notification settings - Fork 52.5k
fix(desktop): resync active chat after gateway reconnect #44443
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -54,6 +54,9 @@ interface GatewayBootOptions { | |
| connection: Awaited<ReturnType<NonNullable<typeof window.hermesDesktop>['getConnection']>> | null | ||
| ) => void | ||
| onGatewayReady: (gateway: HermesGateway | null) => void | ||
| /** Rehydrate the active transcript after a successful reconnect so deltas | ||
| * emitted while the WebSocket was down don't require an app restart. */ | ||
| refreshActiveSession?: () => Promise<void> | ||
| refreshHermesConfig: () => Promise<void> | ||
| refreshSessions: () => Promise<void> | ||
| } | ||
|
|
@@ -62,13 +65,15 @@ export function useGatewayBoot({ | |
| handleGatewayEvent, | ||
| onConnectionReady, | ||
| onGatewayReady, | ||
| refreshActiveSession, | ||
| refreshHermesConfig, | ||
| refreshSessions | ||
| }: GatewayBootOptions) { | ||
| const callbacksRef = useRef({ | ||
| handleGatewayEvent, | ||
| onConnectionReady, | ||
| onGatewayReady, | ||
| refreshActiveSession, | ||
| refreshHermesConfig, | ||
| refreshSessions | ||
| }) | ||
|
|
@@ -77,6 +82,7 @@ export function useGatewayBoot({ | |
| handleGatewayEvent, | ||
| onConnectionReady, | ||
| onGatewayReady, | ||
| refreshActiveSession, | ||
| refreshHermesConfig, | ||
| refreshSessions | ||
| } | ||
|
|
@@ -168,8 +174,12 @@ export function useGatewayBoot({ | |
|
|
||
| reconnectAttempt = 0 | ||
| // Resync state that may have moved on the backend while we were asleep. | ||
| // In addition to the sidebar/config, rehydrate the active transcript: | ||
| // any deltas/completion events emitted while the WebSocket was down are | ||
| // otherwise missing from the renderer until a full app restart. | ||
| await callbacksRef.current.refreshHermesConfig().catch(() => undefined) | ||
| await callbacksRef.current.refreshSessions().catch(() => undefined) | ||
| await callbacksRef.current.refreshActiveSession?.().catch(() => undefined) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This hook is not the only primary reconnect path: |
||
| } catch (err) { | ||
| // OAuth session expired mid-reconnect: surface the actionable "sign in | ||
| // again" message once instead of silently looping the backoff against a | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hydrateFromStoredSession()awaits REST and then replacesmessages(desktop-controller.tsx:508-515), but the WebSocket listener is already live after reconnect. A delta received while that request is pending can be overwritten by the older snapshot. Please make the hydrate response generation-aware or otherwise preserve newer live updates.