feat(native): harden launcher bridge and implement presentation-aware handover

- Upgraded LauncherBackgroundSync to force-hydrate OS metadata (home/tmp) on mount.
- Hardened electron_relay.ts with robust placeholder resolution and global regex.
- Restored safe handover by making native.launch_from_cache presentation-aware.
- Integrated heartbeat and sync status into the formal Launcher Config UI.
- Added comprehensive technical documentation for the 2026 native architecture.
This commit is contained in:
Scott Idem
2026-01-26 15:12:03 -05:00
parent f0c4022675
commit b072857d68
6 changed files with 528 additions and 218 deletions

View File

@@ -43,6 +43,12 @@
if (info) {
$ae_loc.home_directory = info.home_directory;
$ae_loc.tmp_directory = info.tmp_directory;
// Also sync into native_device for redundancy
if (!$ae_loc.native_device) $ae_loc.native_device = {};
$ae_loc.native_device.home_directory = info.home_directory;
$ae_loc.native_device.tmp_directory = info.tmp_directory;
if (log_lvl) console.log('Sync: Native OS metadata hydrated.', { home: info.home_directory });
}
} catch (err) {

View File

@@ -140,85 +140,295 @@
</div>
</section>
<!-- Sync Loop Timers Section -->
<section
class:preset-outlined-warning-300-700={$events_loc.launcher.show_section__sync_timers}
class="sync_timers w-full preset-outlined-surface-300-700 transition-all mb-2"
>
<h3 class="text-center mb-2 text-sm font-semibold w-full">
<button
onclick={() => {
$events_loc.launcher.show_section__sync_timers =
!$events_loc.launcher.show_section__sync_timers;
}}
class="btn btn-sm w-full justify-between"
>
<span>
{#if $events_loc.launcher.show_section__sync_timers}
<span class="fas fa-chevron-down"></span>
{:else}
<span class="fas fa-chevron-right"></span>
{/if}
Native Sync Timers
</span>
</button>
</h3>
<!-- Sync Loop Timers Section -->
<section
class:preset-outlined-warning-300-700={$events_loc.launcher.show_section__sync_timers}
class="sync_timers w-full preset-outlined-surface-300-700 transition-all mb-2"
<div
class="flex flex-col gap-1 items-center justify-start w-full p-2"
class:hidden={!$events_loc.launcher.show_section__sync_timers}
>
{#if $ae_loc.native_device}
<label class="flex flex-row gap-1 items-center justify-start text-xs w-full">
<span class="grow opacity-70">Event Sync (ms):</span>
<input
type="number"
bind:value={$ae_loc.native_device.check_event_loop_period}
class="input input-sm w-24 text-right preset-tonal-surface"
/>
</label>
<label class="flex flex-row gap-1 items-center justify-start text-xs w-full">
<span class="grow opacity-70">Device Heartbeat (ms):</span>
<input
type="number"
bind:value={$ae_loc.native_device.check_event_device_loop_period}
class="input input-sm w-24 text-right preset-tonal-surface"
/>
</label>
<label class="flex flex-row gap-1 items-center justify-start text-xs w-full">
<span class="grow opacity-70">Location Refresh (ms):</span>
<input
type="number"
bind:value={$ae_loc.native_device.check_event_location_loop_period}
class="input input-sm w-24 text-right preset-tonal-surface"
/>
</label>
<label class="flex flex-row gap-1 items-center justify-start text-xs w-full">
<span class="grow opacity-70">Session Scan (ms):</span>
<input
type="number"
bind:value={$ae_loc.native_device.check_event_session_loop_period}
class="input input-sm w-24 text-right preset-tonal-surface"
/>
</label>
<label class="flex flex-row gap-1 items-center justify-start text-xs w-full border-t border-surface-500/20 pt-1 mt-1">
<span class="grow font-semibold text-primary-500">Hash Prefix Length:</span>
<input
type="number"
min="1"
max="8"
bind:value={$ae_loc.native_device.hash_prefix_length}
class="input input-sm w-24 text-right preset-tonal-surface font-bold"
/>
</label>
<div class="text-[9px] text-gray-500 mt-1 italic w-full text-right">
* Prefix: {($ae_loc.native_device.hash_prefix_length || 2)} chars. Reload required.
<h3 class="text-center mb-2 text-sm font-semibold w-full">
<button
onclick={() => {
$events_loc.launcher.show_section__sync_timers =
!$events_loc.launcher.show_section__sync_timers;
}}
class="btn btn-sm w-full justify-between"
>
<span>
{#if $events_loc.launcher.show_section__sync_timers}
<span class="fas fa-chevron-down"></span>
{:else}
<span class="fas fa-chevron-right"></span>
{/if}
Native Sync Timers
</span>
</button>
</h3>
<div
class="flex flex-col gap-1 items-center justify-start w-full p-2"
class:hidden={!$events_loc.launcher.show_section__sync_timers}
>
{#if $ae_loc.native_device}
<label class="flex flex-row gap-1 items-center justify-start text-xs w-full">
<span class="grow opacity-70">Event Sync (ms):</span>
<input
type="number"
bind:value={$ae_loc.native_device.check_event_loop_period}
class="input input-sm w-24 text-right preset-tonal-surface"
/>
</label>
<label class="flex flex-row gap-1 items-center justify-start text-xs w-full">
<span class="grow opacity-70">Device Heartbeat (ms):</span>
<input
type="number"
bind:value={$ae_loc.native_device.check_event_device_loop_period}
class="input input-sm w-24 text-right preset-tonal-surface"
/>
</label>
<label class="flex flex-row gap-1 items-center justify-start text-xs w-full">
<span class="grow opacity-70">Location Refresh (ms):</span>
<input
type="number"
bind:value={$ae_loc.native_device.check_event_location_loop_period}
class="input input-sm w-24 text-right preset-tonal-surface"
/>
</label>
<label class="flex flex-row gap-1 items-center justify-start text-xs w-full">
<span class="grow opacity-70">Session Scan (ms):</span>
<input
type="number"
bind:value={$ae_loc.native_device.check_event_session_loop_period}
class="input input-sm w-24 text-right preset-tonal-surface"
/>
</label>
<label class="flex flex-row gap-1 items-center justify-start text-xs w-full border-t border-surface-500/20 pt-1 mt-1">
<span class="grow font-semibold text-primary-500">Hash Prefix Length:</span>
<input
type="number"
min="1"
max="8"
bind:value={$ae_loc.native_device.hash_prefix_length}
class="input input-sm w-24 text-right preset-tonal-surface font-bold"
/>
</label>
<div class="text-[9px] text-gray-500 mt-1 italic w-full text-right">
* Prefix: {($ae_loc.native_device.hash_prefix_length || 2)} chars. Reload required.
</div>
{:else}
<div class="text-xs text-error-500 italic">No device config hydrated.</div>
{/if}
</div>
</section>
<!-- System Health Section -->
<section
class:preset-outlined-primary-300-700={$events_loc.launcher.show_section__health}
class="system_health w-full preset-outlined-surface-300-700 transition-all mb-2"
>
<h3 class="text-center mb-2 text-sm font-semibold w-full">
<button
onclick={() => {
$events_loc.launcher.show_section__health =
!$events_loc.launcher.show_section__health;
}}
class="btn btn-sm w-full justify-between"
>
<span>
{#if $events_loc.launcher.show_section__health}
<span class="fas fa-chevron-down"></span>
{:else}
<span class="fas fa-chevron-right"></span>
{/if}
System & Sync Health
</span>
<span class="flex gap-1 items-center">
{#if $events_sess.launcher.heartbeat_info.status === 'success'}
<span class="w-2 h-2 rounded-full bg-success-500 animate-pulse"></span>
{:else}
<span class="w-2 h-2 rounded-full bg-error-500"></span>
{/if}
</span>
</button>
</h3>
<div
class="flex flex-col gap-2 p-2 items-center justify-start w-full"
class:hidden={!$events_loc.launcher.show_section__health}
>
<!-- Heartbeat Info -->
<div class="grid grid-cols-2 gap-x-2 gap-y-1 w-full text-[10px] bg-surface-500/5 p-2 rounded border border-surface-500/10">
<span class="opacity-70">Last Heartbeat:</span>
<span class="text-right font-mono {$events_sess.launcher.heartbeat_info.status === 'success' ? 'text-success-500' : 'text-error-500'}">
{$events_sess.launcher.heartbeat_info.last_timestamp || 'Pending...'}
</span>
<span class="opacity-70">Room Sync Status:</span>
<span class="text-right font-mono">
{$events_sess.launcher.sync_stats.cached} / {$events_sess.launcher.sync_stats.total} Files
</span>
{#if $events_sess.launcher.sync_stats.currently_syncing}
<span class="col-span-2 text-center text-primary-500 animate-pulse mt-1 border-t border-primary-500/20 pt-1">
<span class="fas fa-sync fa-spin mr-1"></span>
Syncing: {$events_sess.launcher.sync_stats.currently_syncing}
</span>
{/if}
</div>
{:else}
<div class="text-xs text-error-500 italic">No device config hydrated.</div>
{/if}
</div>
</section>
<!-- Basic Native Info -->
{#if $ae_loc.is_native && $ae_loc.native_device}
<div class="w-full mt-1 flex flex-col gap-1 text-[10px] opacity-80 pl-1 italic">
<div>Host: {$ae_loc.native_device.info_hostname || 'Loading...'}</div>
<div class="truncate">IPs: {$ae_loc.native_device.info_ip_list || '...'}</div>
</div>
{/if}
</div>
</section>
{/if}
<!-- <hr class="w-full my-2 border-1 border-gray-200 dark:border-gray-800 " /> -->