diff --git a/app-catalog/catalog.json b/app-catalog/catalog.json index ca1b6a22..d42cc11d 100644 --- a/app-catalog/catalog.json +++ b/app-catalog/catalog.json @@ -370,6 +370,17 @@ ] } }, + { + "id": "pine", + "title": "Pine", + "version": "1.0.0", + "description": "A private voice assistant for your home. Pine runs speech-to-text (Whisper) and text-to-speech (Piper) on your own node and pairs with a PineVoice satellite speaker, so Home Assistant Assist works locally with nothing sent to the cloud.", + "icon": "/assets/img/app-icons/pine.svg", + "author": "Archipelago", + "category": "home", + "dockerImage": "docker.io/library/nginx:1.27-alpine", + "repoUrl": "https://github.com/rhasspy/wyoming" + }, { "id": "grafana", "title": "Grafana", diff --git a/neode-ui/public/catalog.json b/neode-ui/public/catalog.json index ca1b6a22..d42cc11d 100644 --- a/neode-ui/public/catalog.json +++ b/neode-ui/public/catalog.json @@ -370,6 +370,17 @@ ] } }, + { + "id": "pine", + "title": "Pine", + "version": "1.0.0", + "description": "A private voice assistant for your home. Pine runs speech-to-text (Whisper) and text-to-speech (Piper) on your own node and pairs with a PineVoice satellite speaker, so Home Assistant Assist works locally with nothing sent to the cloud.", + "icon": "/assets/img/app-icons/pine.svg", + "author": "Archipelago", + "category": "home", + "dockerImage": "docker.io/library/nginx:1.27-alpine", + "repoUrl": "https://github.com/rhasspy/wyoming" + }, { "id": "grafana", "title": "Grafana", diff --git a/neode-ui/src/views/appSession/generatedAppSessionConfig.ts b/neode-ui/src/views/appSession/generatedAppSessionConfig.ts index fc59c34b..36c85be9 100644 --- a/neode-ui/src/views/appSession/generatedAppSessionConfig.ts +++ b/neode-ui/src/views/appSession/generatedAppSessionConfig.ts @@ -6,26 +6,29 @@ export const GENERATED_APP_PORTS: Record = { "archy-nbxplorer": 32838, "botfights": 9100, "btcpay-server": 23000, - "did-wallet": 8083, + "did-wallet": 8088, "electrumx": 50002, "fedimint": 8175, "filebrowser": 8083, "gitea": 3001, "grafana": 3000, "homeassistant": 8123, + "immich": 2283, "indeedhub": 7778, "jellyfin": 8096, "lnd-ui": 18083, "mempool": 4080, "mempool-api": 8999, - "morphos-server": 8086, + "morphos-server": 8089, + "netbird": 8087, "nextcloud": 8085, "nostr-rs-relay": 18081, "photoprism": 2342, + "pine": 10380, "portainer": 9000, "router": 8084, "searxng": 8888, - "strfry": 8082, + "strfry": 8090, "uptime-kuma": 3002, "vaultwarden": 8082, } @@ -36,6 +39,7 @@ export const GENERATED_APP_TITLES: Record = { "archy-mempool-db": "Mempool MariaDB", "archy-mempool-web": "Mempool Web", "archy-nbxplorer": "NBXplorer", + "barkd": "Ark Wallet", "bitcoin-core": "Bitcoin Core", "bitcoin-knots": "Bitcoin Knots", "bitcoin-ui": "Bitcoin UI", @@ -45,24 +49,40 @@ export const GENERATED_APP_TITLES: Record = { "did-wallet": "Web5 DID Wallet", "electrs-ui": "Electrs UI", "electrumx": "ElectrumX", - "fedimint": "Fedimint", + "fedimint": "Fedimint Guardian", + "fedimint-clientd": "Fedimint Client", "fedimint-gateway": "Fedimint Gateway", "filebrowser": "File Browser", + "fips-ui": "FIPS Mesh", "gitea": "Gitea", "grafana": "Grafana", "homeassistant": "Home Assistant", + "immich": "Immich", + "immich-postgres": "Immich Postgres", + "immich-redis": "Immich Redis", "indeedhub": "IndeeHub", + "indeedhub-api": "IndeedHub API", + "indeedhub-ffmpeg": "IndeedHub FFmpeg Worker", + "indeedhub-minio": "IndeedHub MinIO", + "indeedhub-postgres": "IndeedHub Postgres", + "indeedhub-redis": "IndeedHub Redis", + "indeedhub-relay": "IndeedHub Nostr Relay", "jellyfin": "Jellyfin", "lightning-stack": "Lightning Stack", "lnd": "LND", "lnd-ui": "LND UI", "mempool": "Mempool Explorer", "mempool-api": "Mempool API", - "meshtastic": "Meshtastic", "morphos-server": "MorphOS Server", + "netbird": "NetBird", + "netbird-dashboard": "NetBird Dashboard", + "netbird-server": "NetBird Server", "nextcloud": "Nextcloud", "nostr-rs-relay": "Nostr Relay (Rust)", "photoprism": "PhotoPrism", + "pine": "Pine", + "pine-piper": "Pine Piper (TTS)", + "pine-whisper": "Pine Whisper (STT)", "portainer": "Portainer", "router": "Mesh Router", "searxng": "SearXNG", @@ -76,8 +96,10 @@ export const GENERATED_NEW_TAB_APPS = new Set([ "gitea", "grafana", "homeassistant", + "immich", "nextcloud", "photoprism", + "pine", "portainer", "uptime-kuma", "vaultwarden", diff --git a/neode-ui/src/views/apps/appsConfig.ts b/neode-ui/src/views/apps/appsConfig.ts index ec4ca8da..7903ed22 100644 --- a/neode-ui/src/views/apps/appsConfig.ts +++ b/neode-ui/src/views/apps/appsConfig.ts @@ -26,6 +26,10 @@ export const SERVICE_NAMES = new Set([ 'indeedhub-relay', 'indeedhub-build_api_1', 'indeedhub-build_ffmpeg-worker_1', 'indeedhub-build_postgres_1', 'indeedhub-build_redis_1', 'indeedhub-build_minio_1', 'indeedhub-build_minio-init_1', 'indeedhub-build_relay_1', + // Pine voice-assistant stack: the two Wyoming engines are backends (STT/TTS) + // reached by Home Assistant over host.containers.internal — the user-facing + // card is "pine" (the setup/status launcher), so the engines go to Services. + 'pine-whisper', 'pine-piper', ]) const INTERNAL_TOOLING_NAMES = new Set([ @@ -61,7 +65,7 @@ export const APP_CATEGORY_MAP: Record = { 'fedimint': 'money', 'fedimint-gateway': 'money', 'indeedhub': 'media', 'jellyfin': 'media', 'photoprism': 'media', 'immich': 'media', 'nextcloud': 'data', 'vaultwarden': 'data', 'filebrowser': 'data', 'cryptpad': 'data', - 'homeassistant': 'home', 'lorabell': 'home', 'endurain': 'home', + 'homeassistant': 'home', 'lorabell': 'home', 'endurain': 'home', 'pine': 'home', 'searxng': 'community', 'ollama': 'community', 'grafana': 'data', 'gitea': 'data', 'nostrudel': 'nostr', 'tailscale': 'networking', 'netbird': 'networking', 'nginx-proxy-manager': 'networking', 'portainer': 'networking', @@ -212,6 +216,7 @@ const SERVICE_ICON_PREFIXES: Array<[string, string]> = [ ['indeedhub-', '/assets/img/app-icons/indeedhub.png'], ['immich-', '/assets/img/app-icons/immich.png'], ['immich_', '/assets/img/app-icons/immich.png'], + ['pine-', '/assets/img/app-icons/pine.svg'], ] function serviceParentIcon(id: string): string | undefined {