diff --git a/documentation/MODULE__AE_Events_PressMgmt_Launcher.md b/documentation/MODULE__AE_Events_PressMgmt_Launcher.md index 75b13105..d17abff9 100644 --- a/documentation/MODULE__AE_Events_PressMgmt_Launcher.md +++ b/documentation/MODULE__AE_Events_PressMgmt_Launcher.md @@ -311,12 +311,14 @@ The Electron app zero-configs itself: 3. Rename to original filename (e.g., `Abstract_101.pptx`) 4. OS opens the file (Keynote, PowerPoint, Preview, etc.) -**Configurable launch behavior:** The open/launch command in step 4 can be overridden -per file extension via `event_device.data_json.launch_profiles` (device-level config) or -`event.launcher.launch_profiles` (event-level fallback). Templates use `{{path}}` as the -file path placeholder; AppleScript or `shell:` prefixed commands are both supported. No -Electron rebuild required to change how files open — edit config in Aether and it applies -See `PROJECT__AE_Events_Launcher_Native_integration.md` Section 8. +**Configurable launch behavior:** The file-open behavior is driven by a Launch Profile, not +just a command string. Profiles are stored per file extension in +`event_device.data_json.launch_profiles` (device-level config) or +`event.launcher.launch_profiles` (event-level fallback). A profile can choose the app, +display mode, open command, and post-open automation. The resolved native template uses +`{{path}}` as the file path placeholder; AppleScript or `shell:` prefixed commands are both +supported. No Electron rebuild is required to change how files open — edit config in Aether +and it applies immediately. See `PROJECT__AE_Events_Launcher_Native_integration.md` Section 8. Versioning is handled automatically: when a presenter uploads an updated file, the new hash is cached separately and the old one remains intact. diff --git a/documentation/PROJECT__AE_Events_Launcher_Native_integration.md b/documentation/PROJECT__AE_Events_Launcher_Native_integration.md index 8b8a8e7a..15c7a862 100644 --- a/documentation/PROJECT__AE_Events_Launcher_Native_integration.md +++ b/documentation/PROJECT__AE_Events_Launcher_Native_integration.md @@ -40,8 +40,12 @@ The integration is built on a decoupled three-layer communication model to ensur - **File:** `src/lib/electron/electron_relay.ts` - **Role:** Provides a clean, typed API for Svelte components. - **Responsibilities:** - - Mapping `camelCase` UI triggers to `snake_case` IPC calls. - - Implementing "Smart Fallbacks" (e.g., resolving `[home]` placeholders if the bridge is partially hydrated). + - Mapping `camelCase` UI triggers to `snake_case` IPC calls. + - Resolving a Launch Profile to a single `native_template` string before crossing IPC. + +The reason for this split is simple: Launch Profiles are policy, while Native Templates are +executable strings. Keeping that distinction explicit prevents the bridge from mixing config +objects with runtime commands. --- @@ -147,7 +151,7 @@ no-op when `window.aetherNative` is not present (i.e., in browser/non-native mod - `check_cache({cache_root, hash, hash_prefix_length?, verify_hash?})` — Verifies a file exists in the local hashed cache. `verify_hash: true` re-hashes to confirm integrity. - `download_to_cache({url, cache_root, hash, api_key, account_id, hash_prefix_length?})` — Streams a file download to the hashed cache with SHA-256 integrity check. Stale `.tmp` files (older than 5 min) from crashed downloads are cleaned up automatically on each call. - `copy_from_cache_to_temp({cache_root, hash, temp_root, filename, hash_prefix_length?})` — **Preferred primitive.** Copies a cached file to temp and returns `{ success, path }`. The Svelte caller decides what to do next (run a script, open it, etc.). -- `launch_from_cache({cache_root, hash, temp_root, filename, hash_prefix_length?, script_template?})` — Combines copy + launch in one call. Uses `script_template` if provided, otherwise falls back to hardcoded extension logic. See **Configurable Launch Scripts** below. +- `launch_from_cache({cache_root, hash, temp_root, filename, hash_prefix_length?, native_template?})` — Combines copy + launch in one call. Executes the provided `native_template` string after the file is copied to temp. If no template is supplied, treat it as an error and do not rely on Electron-side defaults. > `hash_prefix_length` defaults to `2` throughout. Do not change without coordinating all devices — mismatched values create orphaned cache subdirectories. @@ -180,22 +184,30 @@ All paths passed to native handlers should use tokens rather than hardcoded OS p --- -## 8. Configurable Launch Scripts (No-Rebuild File Handling) +## 8. Launch Profiles and Native Templates (No-Rebuild File Handling) +This launcher uses two related concepts: -To avoid requiring a full Electron rebuild for changes to how files are opened, `launch_from_cache` -supports an optional `script_template` parameter. When provided, Electron runs the template -instead of its built-in hardcoded logic. The hardcoded logic remains intact as the fallback -when no template is configured. +- **Launch Profile**: the Svelte-side config object keyed by file extension. A profile decides + which app to use, whether to extend or mirror displays, whether to use an explicit open + command, whether to run post-open automation, and how long to wait before running it. +- **Native Template**: the single AppleScript or shell command string handed to Electron after + Svelte resolves the profile. This is what Electron actually executes. -### Template Formats +The Svelte launcher resolves a profile and then passes a native template string to +`launch_from_cache`. Electron only executes the template it receives. If Svelte has not +resolved a template yet, it should stop before IPC and surface a missing-profile error. +This keeps all fallback logic in Svelte, where it can be edited without rebuilding Electron. +The native layer should not invent or guess a default launch path. + +### Native Template Formats | Format | Example | | :--- | :--- | | **AppleScript** (macOS) | Multi-line AppleScript string with `{{path}}` placeholder | | **Shell command** | String prefixed with `shell:` — e.g. `shell:open "{{path}}"` | -The placeholder `{{path}}` is replaced with the full resolved path to the file in the -temp directory (after the atomic copy from cache). +The placeholder `{{path}}` is replaced with the full resolved path to the file in the temp +directory after the atomic copy from cache. ### Where to Configure @@ -207,13 +219,20 @@ Launch profiles are resolved in priority order by `get_launch_profile()` in 2. **`$events_loc.launcher.launch_profiles`** — Local persistent config. Editable via the Launcher config UI (planned) or direct `localStorage` manipulation. -If neither is set, `script_template` is `null` and Electron uses its built-in hardcoded defaults. +If neither is set, the resolved native template is `null` and the launcher should not call +Electron until an explicit template is available. + +Why: this avoids a second hidden source of truth. The profile map can evolve independently of +the executable string, and Electron stays a thin executor rather than a policy engine. ### Key Format Keys are lowercase file extensions without the dot. A `"default"` key catches all unrecognised extensions. +The JSON below illustrates the `native_template` emitted after profile resolution, not the +full Launch Profile object schema. + ```json // event_device.data_json.launch_profiles example { diff --git a/documentation/TODO__Agents.md b/documentation/TODO__Agents.md index 983f143d..e3785742 100644 --- a/documentation/TODO__Agents.md +++ b/documentation/TODO__Agents.md @@ -6,23 +6,27 @@ ## 🔴 CMSC Charlotte — May 27 (Presentation Management) **Drive down:** May 25 | **Setup:** May 26 morning | **Show:** May 27+ -**[Electron/Launcher] Clean up presentation file launch scripts** — BGH show revealed issues -with the scripts used to open/launch presentation files. Architecture decision: move launch +**[Electron/Launcher] Clean up presentation file launch profiles** — BGH show revealed issues +with the profiles used to open/launch presentation files. Architecture decision: move launch logic to the Svelte side so it can be changed without an Electron rebuild. Electron becomes a thin OS primitive layer; all business logic lives in Svelte and device config. +Why this matters: the profile map is policy, while the native template is the exact runtime +command. Keeping those separate avoids a second hidden source of truth and keeps Electron from +guessing defaults. + **Electron groundwork (2026-05-11) — DONE:** - [x] `run_osascript` hardened — temp `.scpt` file approach; handles multi-line + special chars - [x] `native:copy-from-cache-to-temp` primitive added — copy to tmp, caller decides launch -- [x] `native:launch-from-cache` accepts optional `script_template` — AppleScript or `shell:` prefix; falls back to hardcoded defaults when null -- [x] `get_launch_script_template()` in `launcher_file_cont.svelte` reads from device config then event config; passes result to `launch_from_cache` +- [x] `native:launch-from-cache` executes a provided `native_template` string — AppleScript or `shell:` prefix; no Electron-side fallback +- [x] `get_launch_profile()` in `launcher_file_cont.svelte` reads from device config then event config; resolves to a `native_template` string and passes it to `launch_from_cache` **Svelte-side migration — remaining before May 26:** -- [ ] **[Launcher] Built-in Svelte default templates** — move the "known good" pptx/key/pdf - AppleScript strings out of Electron hardcode and into a Svelte constants file (e.g. - `ae_launcher__default_launch_profiles.ts`). Priority: `get_launch_profile()` already - checks device config and event config; add a 3rd fallback to these Svelte defaults before - returning `null`. This means Electron's hardcoded defaults become the last-resort only. +- [ ] **[Launcher] Built-in Svelte default profiles** — move the "known good" pptx/key/pdf + policy objects into a Svelte constants file (e.g. `ae_launcher__default_launch_profiles.ts`). + Priority: `get_launch_profile()` already checks device config and event config; add a 3rd + fallback to these Svelte defaults before returning `null`. Keep the fallback in Svelte, not + in Electron. - [ ] **[Launcher] Composable open flow** — refactor `handle_open_file()` to use `copy_from_cache_to_temp` + `run_osascript` / `run_cmd` directly instead of the all-in-one `launch_from_cache`. Finer error handling at each step (verify copy succeeded before