diff --git a/packages/app/src/contexts/daemon-registry-context.tsx b/packages/app/src/contexts/daemon-registry-context.tsx index e4db52d0c..d06918947 100644 --- a/packages/app/src/contexts/daemon-registry-context.tsx +++ b/packages/app/src/contexts/daemon-registry-context.tsx @@ -128,12 +128,16 @@ export function DaemonRegistryProvider({ children }: { children: ReactNode }) { const existing = readDaemons(); const now = new Date().toISOString(); const normalizedEndpoints = offer.endpoints.map((endpoint) => normalizeHostPort(endpoint)); - const relayEndpoint = - offer.relay?.endpoint - ? normalizeHostPort(offer.relay.endpoint) - : offer.relay === undefined && normalizedEndpoints.length > 0 - ? normalizedEndpoints[normalizedEndpoints.length - 1] - : null; + let relayEndpoint: string | null = null; + if (offer.relay?.endpoint) { + relayEndpoint = normalizeHostPort(offer.relay.endpoint); + } else if (offer.relay === undefined && normalizedEndpoints.length > 0) { + // Back-compat: older offers encoded relay endpoint as the last entry. + relayEndpoint = normalizedEndpoints[normalizedEndpoints.length - 1]; + } + const relay = relayEndpoint + ? { endpoint: relayEndpoint, sessionId: offer.sessionId } + : null; const matchIndex = existing.findIndex((daemon) => daemon.daemonPublicKeyB64 === offer.daemonPublicKeyB64); if (matchIndex !== -1) { @@ -141,7 +145,7 @@ export function DaemonRegistryProvider({ children }: { children: ReactNode }) { ...existing[matchIndex], daemonPublicKeyB64: offer.daemonPublicKeyB64, endpoints: normalizedEndpoints, - relay: relayEndpoint ? { endpoint: relayEndpoint, sessionId: offer.sessionId } : null, + relay, updatedAt: now, }; const next = [...existing]; @@ -155,7 +159,7 @@ export function DaemonRegistryProvider({ children }: { children: ReactNode }) { label: deriveLabelFromEndpoint(normalizedEndpoints[0] ?? "Unnamed Host"), endpoints: normalizedEndpoints, daemonPublicKeyB64: offer.daemonPublicKeyB64, - relay: relayEndpoint ? { endpoint: relayEndpoint, sessionId: offer.sessionId } : null, + relay, createdAt: now, updatedAt: now, metadata: null, diff --git a/packages/server/src/client/daemon-client-v2.ts b/packages/server/src/client/daemon-client-v2.ts index 0e82bb815..402d87224 100644 --- a/packages/server/src/client/daemon-client-v2.ts +++ b/packages/server/src/client/daemon-client-v2.ts @@ -323,13 +323,19 @@ export class DaemonClientV2 { const shouldUseRelayE2ee = this.config.e2ee?.enabled === true && isRelayClientWebSocketUrl(this.config.url); - const transportFactory = shouldUseRelayE2ee - ? createRelayE2eeTransportFactory( - baseTransportFactory, - this.config.e2ee?.daemonPublicKeyB64, - this.logger - ) - : baseTransportFactory; + + let transportFactory = baseTransportFactory; + if (shouldUseRelayE2ee) { + const daemonPublicKeyB64 = this.config.e2ee?.daemonPublicKeyB64; + if (!daemonPublicKeyB64) { + throw new Error("daemonPublicKeyB64 is required for relay E2EE"); + } + transportFactory = createRelayE2eeTransportFactory({ + baseFactory: baseTransportFactory, + daemonPublicKeyB64, + logger: this.logger, + }); + } const transport = transportFactory({ url: this.config.url, headers }); this.transport = transport; @@ -2345,18 +2351,14 @@ function createWebSocketTransportFactory( }; } -function createRelayE2eeTransportFactory( - baseFactory: DaemonTransportFactory, - daemonPublicKeyB64: string | undefined, - logger: Logger -): DaemonTransportFactory { - if (!daemonPublicKeyB64) { - throw new Error("daemonPublicKeyB64 is required for relay E2EE"); - } - +function createRelayE2eeTransportFactory(args: { + baseFactory: DaemonTransportFactory; + daemonPublicKeyB64: string; + logger: Logger; +}): DaemonTransportFactory { return ({ url, headers }) => { - const base = baseFactory({ url, headers }); - return createEncryptedTransport(base, daemonPublicKeyB64, logger); + const base = args.baseFactory({ url, headers }); + return createEncryptedTransport(base, args.daemonPublicKeyB64, args.logger); }; }