diff --git a/src/connectLocalController.ts b/src/connectLocalController.ts index 77931e1..158c21d 100644 --- a/src/connectLocalController.ts +++ b/src/connectLocalController.ts @@ -30,6 +30,10 @@ export class ConnectLocalController { resolve: (value: LocalAgentServerMessage & { type: 'pair.ok' }) => void; reject: (error: Error) => void; }> = []; + private reconnectWaiters: Array<{ + resolve: (value: LocalAgentServerMessage & { type: 'reconnect.ok' }) => void; + reject: (error: Error) => void; + }> = []; constructor(deps: ConnectLocalControllerDeps) { this.pi = deps.pi; @@ -150,14 +154,29 @@ export class ConnectLocalController { } try { await this.ensureClient(stored.wsUrl || this.wsUrl); - this.client!.send({ - type: 'reconnect', - credential: stored.credential, - projectName: stored.projectName, - connectionEpoch: this.connectionEpoch, + const reconnectOk = await new Promise((resolve, reject) => { + const timeout = setTimeout(() => reject(new Error('Reconnect timed out')), 30_000); + this.reconnectWaiters.push({ + resolve: (value) => { + clearTimeout(timeout); + resolve(value); + }, + reject: (error) => { + clearTimeout(timeout); + reject(error); + }, + }); + this.client!.send({ + type: 'reconnect', + credential: stored.credential, + projectName: stored.projectName, + connectionEpoch: this.connectionEpoch, + }); }); - this.projectName = stored.projectName; + this.projectName = reconnectOk.projectName; + this.connectionEpoch = reconnectOk.connectionEpoch; } catch { + this.projectName = undefined; /* extension must not block Pi; reconnect can be retried manually */ } } @@ -190,9 +209,19 @@ export class ConnectLocalController { waiter?.resolve(message); return; } + if (message.type === 'reconnect.ok') { + const waiter = this.reconnectWaiters.shift(); + waiter?.resolve(message); + return; + } if (message.type === 'error') { - const waiter = this.pairWaiters.shift(); - waiter?.reject(new Error(message.message)); + const pairWaiter = this.pairWaiters.shift(); + if (pairWaiter) { + pairWaiter.reject(new Error(message.message)); + return; + } + const reconnectWaiter = this.reconnectWaiters.shift(); + reconnectWaiter?.reject(new Error(message.message)); return; } if (message.type === 'task.dispatch') {