| 861 | }, |
| 862 | |
| 863 | onResync(sessionId: string, currentSeq: number, epoch?: string) { |
| 864 | // Flush streaming deltas already queued so they render on the |
| 865 | // pre-snapshot state (the snapshot is authoritative and will overwrite |
| 866 | // them). Stragglers that arrive during the snapshot fetch are drained |
| 867 | // again right before the snapshot write inside syncSessionFromSnapshot, |
| 868 | // so they are applied to the pre-snapshot array too rather than on top |
| 869 | // of the fresh snapshot (which would duplicate text / tool output). |
| 870 | enqueueEvent.flush(); |
| 871 | // The server-announced cursor is only a hint; the snapshot fetch |
| 872 | // returns the authoritative {asOfSeq, epoch} and re-subscribes. |
| 873 | if (epoch !== undefined) epochBySession[sessionId] = epoch; |
| 874 | void currentSeq; |
| 875 | snapshotSyncRunner.request(sessionId); |
| 876 | }, |
| 877 | |
| 878 | onError(_code: number, msg: string, _fatal: boolean) { |
| 879 | pushWarning({ |