feat: upgrade launcher WebSocket to V3 protocol

- New element_websocket_v3.svelte:
  - URL path /v3/ws/group/{id}/client/{id}
  - Auth via ?api_key=...&jwt=... query params (browsers can't set WS headers)
  - Strict WS_Message_V3 schema: msg_type + target fields
  - 45s heartbeat to maintain Redis presence TTL
  - Self-echo detection via from_id (server-stamped)
  - Target 'group' (was 'all'), 'direct' (was 'dm')
- launcher/+layout.svelte:
  - Swap Element_websocket_v2 -> Element_websocket_v3
  - Add api_key and jwt props for V3 auth
  - Fix handle_ws_recv: type -> msg_type (V3 schema)
  - Remove unused 'type' prop passed to element
This commit is contained in:
Scott Idem
2026-03-11 17:50:08 -04:00
parent 3f5f554595
commit 5db66bc888
2 changed files with 407 additions and 4 deletions

View File

@@ -54,7 +54,7 @@
import Launcher_cfg from '../launcher_cfg.svelte';
import Launcher_menu from '../launcher_menu.svelte';
import Launcher_session_view from '../launcher_session_view.svelte';
import Element_websocket_v2 from '$lib/elements/element_websocket_v2.svelte';
import Element_websocket_v3 from '$lib/elements/element_websocket_v3.svelte';
// *** Set initial variables
// NOTE: Derived from data.account_id (prop) instead of $slct.account_id (store)
@@ -288,7 +288,8 @@
function handle_ws_recv(ws_recv_status: any) {
if (log_lvl) console.log('*** handle_ws_recv() ***', ws_recv_status);
if (ws_recv_status.type == 'cmd' && ws_recv_status.cmd) {
// V3 schema uses msg_type instead of type
if (ws_recv_status.msg_type == 'cmd' && ws_recv_status.cmd) {
let cmd = ws_recv_status.cmd;
if ($events_loc.launcher.controller != 'remote') return;
@@ -1001,15 +1002,16 @@
</Modal>
{#if $events_loc.launcher.controller_group_code && $events_loc.launcher.ws_connect}
<Element_websocket_v2
<Element_websocket_v3
{log_lvl}
bind:ws_connect={$events_loc.launcher.ws_connect}
bind:ws_connect_status={$events_sess.launcher.ws_connect_status}
ws_server={$ae_api.fqdn}
api_key={$ae_api.api_secret_key}
jwt={$ae_loc.jwt}
bind:group_id={$events_loc.launcher.controller_group_code}
bind:client_id={$events_loc.launcher.controller_client_id}
bind:cmd={$events_sess.launcher.controller_cmd}
type={'cmd'}
bind:trigger_send={$events_sess.launcher.controller_trigger_send}
bind:trigger_connect={$events_sess.launcher.trigger__ws_connect}
bind:trigger_disconnect={$events_sess.launcher.trigger__ws_disconnect}