diff --git a/neode-ui/src/api/remote-relay.ts b/neode-ui/src/api/remote-relay.ts index be04e57a..d6eee450 100644 --- a/neode-ui/src/api/remote-relay.ts +++ b/neode-ui/src/api/remote-relay.ts @@ -38,6 +38,13 @@ export const companionInputActive = ref(false) let ws: WebSocket | null = null let shouldReconnect = true let reconnectTimer: ReturnType | null = null +// Exponential backoff for the relay socket. It's a secondary feature (companion +// input), so when the backend is down it must NOT hammer a fixed-interval +// reconnect — that floods the console/network with failed-WS noise for the whole +// outage. Back off 1s → 30s, reset on a successful open. (Mirrors websocket.ts.) +let relayReconnectAttempts = 0 +const RELAY_RECONNECT_BASE_MS = 1000 +const RELAY_RECONNECT_MAX_MS = 30_000 let cursorEl: HTMLDivElement | null = null let companionTimeout: ReturnType | null = null let inputFlickerTimeout: ReturnType | null = null @@ -332,6 +339,7 @@ function doConnect() { ws.onopen = () => { relayConnected.value = true + relayReconnectAttempts = 0 // healthy again — reset backoff if (import.meta.env.DEV) console.log('[RemoteRelay] Connected') } @@ -343,7 +351,12 @@ function doConnect() { relayConnected.value = false ws = null if (shouldReconnect) { - reconnectTimer = setTimeout(doConnect, 5000) + const delay = Math.min( + RELAY_RECONNECT_BASE_MS * 2 ** relayReconnectAttempts, + RELAY_RECONNECT_MAX_MS, + ) + relayReconnectAttempts++ + reconnectTimer = setTimeout(doConnect, delay) } } @@ -379,6 +392,7 @@ export function requestExternalOpen(url: string): boolean { /** Start the remote relay listener. Connects to /ws/remote-relay. */ export function startRemoteRelay() { shouldReconnect = true + relayReconnectAttempts = 0 doConnect() } diff --git a/neode-ui/src/views/discover/curatedApps.ts b/neode-ui/src/views/discover/curatedApps.ts index 22635d7c..c6fc0fff 100644 --- a/neode-ui/src/views/discover/curatedApps.ts +++ b/neode-ui/src/views/discover/curatedApps.ts @@ -85,7 +85,7 @@ export function getCuratedAppList(): MarketplaceApp[] { { id: 'grafana', title: 'Grafana', version: '10.2.0', description: 'Analytics and monitoring platform. Dashboards for your node metrics and system health.', icon: '/assets/img/app-icons/grafana.png', author: 'Grafana Labs', dockerImage: `${R}/grafana:10.2.0`, repoUrl: 'https://github.com/grafana/grafana' }, { id: 'searxng', title: 'SearXNG', version: '2024.1.0', description: 'Privacy-respecting metasearch engine. Search the internet without being tracked or profiled.', icon: '/assets/img/app-icons/searxng.png', author: 'SearXNG', dockerImage: `${R}/searxng:latest`, repoUrl: 'https://github.com/searxng/searxng' }, { id: 'ollama', title: 'Ollama', version: '0.5.4', description: 'Run AI models locally. Llama, Mistral, and more — on your hardware, completely private.', icon: '/assets/img/app-icons/ollama.png', author: 'Ollama', dockerImage: `${R}/ollama:latest`, repoUrl: 'https://github.com/ollama/ollama' }, - { id: 'cryptpad', title: 'CryptPad', version: '2024.12.0', description: 'End-to-end encrypted documents, spreadsheets, and presentations. Zero-knowledge collaboration.', icon: '/assets/img/app-icons/cryptpad.webp', author: 'XWiki SAS', dockerImage: `${R}/cryptpad:2024.12.0`, repoUrl: 'https://github.com/cryptpad/cryptpad' }, + { id: 'cryptpad', title: 'CryptPad', version: '2024.12.0', description: 'End-to-end encrypted documents, spreadsheets, and presentations. Zero-knowledge collaboration.', icon: '/assets/icon/favico-black-v2.svg', author: 'XWiki SAS', dockerImage: `${R}/cryptpad:2024.12.0`, repoUrl: 'https://github.com/cryptpad/cryptpad' }, { id: 'nextcloud', title: 'Nextcloud', version: '29', description: 'Your own private cloud. File sync, calendars, contacts — all on your hardware.', icon: '/assets/img/app-icons/nextcloud.webp', author: 'Nextcloud', dockerImage: `${R}/nextcloud:29`, repoUrl: 'https://github.com/nextcloud/server' }, { id: 'vaultwarden', title: 'Vaultwarden', version: '1.30.0', description: 'Self-hosted password vault. Bitwarden-compatible with zero-knowledge encryption.', icon: '/assets/img/app-icons/vaultwarden.webp', author: 'Vaultwarden', dockerImage: `${R}/vaultwarden:1.30.0-alpine`, repoUrl: 'https://github.com/dani-garcia/vaultwarden' }, { id: 'jellyfin', title: 'Jellyfin', version: '10.8.13', description: 'Free media server. Stream your movies, music, and photos to any device.', icon: '/assets/img/app-icons/jellyfin.webp', author: 'Jellyfin', dockerImage: `${R}/jellyfin:10.8.13`, repoUrl: 'https://github.com/jellyfin/jellyfin' }, diff --git a/neode-ui/src/views/marketplace/marketplaceData.ts b/neode-ui/src/views/marketplace/marketplaceData.ts index 8d343614..668a9dfd 100644 --- a/neode-ui/src/views/marketplace/marketplaceData.ts +++ b/neode-ui/src/views/marketplace/marketplaceData.ts @@ -234,7 +234,7 @@ export function getCuratedAppList(): MarketplaceApp[] { title: 'CryptPad', version: '2024.12.0', description: 'End-to-end encrypted documents, spreadsheets, and presentations. Zero-knowledge collaboration.', - icon: '/assets/img/app-icons/cryptpad.webp', + icon: '/assets/icon/favico-black-v2.svg', author: 'XWiki SAS', dockerImage: `${REGISTRY}/cryptpad:2024.12.0`, manifestUrl: undefined,