fix(sync): preserve host replicas across provider remounts

Make the host runtime own session and setup replicas for the registered host lifetime. Provider remounts can then reattach without clearing directory snapshots or timeline cursors.
This commit is contained in:
Mohamed Boudra
2026-07-21 13:44:23 +02:00
parent 8aa55db1e8
commit d0456b1943
4 changed files with 39 additions and 84 deletions
+23 -4
View File
@@ -40,6 +40,7 @@ import { getDesktopHost } from "@/desktop/host";
import { CLIENT_CAPS } from "@getpaseo/protocol/client-capabilities";
import { BROWSER_AUTOMATION_COMMAND_NAMES } from "@getpaseo/protocol/browser-automation/rpc-schemas";
import { useSessionStore } from "@/stores/session-store";
import { useWorkspaceSetupStore } from "@/stores/workspace-setup-store";
import { invalidateCheckoutGitQueriesForServer } from "@/git/query-keys";
import { queryClient } from "@/data/query-client";
import {
@@ -1583,8 +1584,6 @@ export class HostRuntimeStore {
}
rekeyMap(this.controllers, oldServerId, newServerId);
controller.adoptReconciledServerId(newServerId);
rekeyMap(this.lastConnectionStatusByServer, oldServerId, newServerId);
rekeyMap(this.directoryBootstrapInFlight, oldServerId, newServerId);
this.replicaCache.reconcileServerId(oldServerId, newServerId);
@@ -1597,7 +1596,10 @@ export class HostRuntimeStore {
markAgentError: (error) => controller.markAgentDirectorySyncError(error),
});
this.directorySyncByServer.set(newServerId, directory);
controller.adoptReconciledServerId(newServerId);
const snapshot = controller.getSnapshot();
this.clearHostReplica(oldServerId);
this.syncSessionReplica(newServerId, snapshot);
directory.connectionChanged({
client: snapshot.client,
status: snapshot.connectionStatus === "online" ? "online" : "offline",
@@ -1899,6 +1901,7 @@ export class HostRuntimeStore {
this.directoryBootstrapInFlight.delete(serverId);
this.directorySyncByServer.get(serverId)?.dispose();
this.directorySyncByServer.delete(serverId);
this.clearHostReplica(serverId);
void controller.stop();
this.emit(serverId);
}
@@ -1936,8 +1939,10 @@ export class HostRuntimeStore {
controller.getSnapshot().connectionStatus,
);
controller.subscribe(() => {
this.maybeAutoBootstrapDirectories(host.serverId);
this.emit(host.serverId);
const snapshot = controller.getSnapshot();
this.syncSessionReplica(snapshot.serverId, snapshot);
this.maybeAutoBootstrapDirectories(snapshot.serverId);
this.emit(snapshot.serverId);
});
void controller
.start(
@@ -1955,6 +1960,20 @@ export class HostRuntimeStore {
}
}
private syncSessionReplica(serverId: string, snapshot: HostRuntimeSnapshot): void {
if (!snapshot.client) {
return;
}
const sessionStore = useSessionStore.getState();
sessionStore.initializeSession(serverId, snapshot.client, snapshot.clientGeneration);
sessionStore.updateSessionClient(serverId, snapshot.client, snapshot.clientGeneration);
}
private clearHostReplica(serverId: string): void {
useSessionStore.getState().clearSession(serverId);
useWorkspaceSetupStore.getState().clearServer(serverId);
}
private maybeAutoBootstrapDirectories(serverId: string): void {
const controller = this.controllers.get(serverId);
if (!controller) {