Add Fox Desktop design spec

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
main
boksbc 2026-05-11 21:42:59 +02:00
commit c6ddbc3dc9
1 changed files with 182 additions and 0 deletions

View File

@ -0,0 +1,182 @@
# Fox Desktop — Design Spec
**Datum:** 2026-05-11
**Status:** Genehmigt
## Überblick
Fox Desktop ist eine native Mac-App (Electron), die als dünne Hülle um die bestehende Laravel-HUD-App (`fox.pxo.at/hud`) fungiert. Electron fügt native Mac-Fähigkeiten hinzu, ohne das HUD neu zu schreiben.
## Architektur
```
Mac OS
├── Tray Icon (Menu Bar)
├── BrowserWindow (Overlay, fullscreen, always-on-top)
│ └── lädt https://fox.pxo.at/hud
│ └── preload.js injiziert window.foxBridge
├── Global Shortcut: Cmd+Shift+F
└── Python Subprocess: openwakeword ("hey_jarvis")
└── stdout "WAKE" → IPC → showHud()
```
Der Electron-Main-Process hat **keine** eigene WebSocket-Verbindung zu Reverb. Der WebSocket-Kanal gehört der HUD-Seite selbst. Electron ist reiner Plattform-Layer.
## Prinzipien
- **Pure Shell:** Electron kapselt, erweitert nicht die App-Logik
- **Bridge ist optional:** `window.foxBridge` wird nur in Electron injiziert; das HUD funktioniert im normalen Browser unverändert weiter
- **Kein Vite Build:** Es gibt kein eigenes Frontend — nur Electron-Module und Python-Script
- **Kein electron-builder** vorerst — erst nach stabilem Dev-Setup
## Dateien
| Datei | Aufgabe |
|---|---|
| `package.json` | Electron-App-Konfiguration, npm-Scripts |
| `electron/main.js` | App-Lifecycle, IPC-Handler, globaler Shortcut |
| `electron/hud.js` | BrowserWindow erstellen, show/hide mit Transition |
| `electron/tray.js` | Menu Bar Icon (Template Image) + Kontextmenü |
| `electron/wakeword.js` | Python-Subprocess starten, Auto-Restart bei Absturz |
| `electron/mac-agent.js` | AppleScript-Ausführung via osascript |
| `electron/preload.js` | `window.foxBridge` in HUD-Seite injizieren |
| `python/wakeword.py` | OpenWakeWord Loop, schreibt "WAKE" auf stdout |
| `assets/fox-tray.png` | 16×16 Menu Bar Icon (Template Image) |
## Datenflüsse
### HUD öffnen (Wakeword)
```
"hey jarvis" gesprochen
→ python/wakeword.py erkennt Wakeword
→ stdout: "WAKE\n"
→ electron/wakeword.js liest stdout
→ IPC intern → showHud()
→ BrowserWindow.show() + focus()
→ webContents.send('hud-show')
→ HUD CSS-Transition startet
```
### HUD öffnen (Tastaturkürzel / Tray)
```
Cmd+Shift+F gedrückt ODER Tray-Icon geklickt
→ main.js globalShortcut / tray.on('click')
→ showHud()
```
### Mac-Befehl aus HUD
```
HUD JavaScript: await window.foxBridge.macCommand('spotify_play')
→ preload.js: ipcRenderer.invoke('mac-command', 'spotify_play')
→ main.js IPC Handler
→ electron/mac-agent.js: executeMacCommand('spotify_play')
→ osascript: tell application "Spotify" to play
→ Rückgabewert { success: true, output: '' } → HUD
```
### HUD schließen
```
ESC im HUD ODER foxBridge.hideHud() ODER Tray-Menü "Verstecken"
→ ipcRenderer.send('hide-hud')
→ main.js → hideHud()
→ webContents.send('hud-hide') ← CSS-Transition startet
→ setTimeout 600ms → BrowserWindow.hide()
```
## BrowserWindow Konfiguration
```javascript
{
width: screenWidth,
height: screenHeight,
x: 0, y: 0,
frame: false,
transparent: true,
alwaysOnTop: true,
show: false,
skipTaskbar: true,
hasShadow: false,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
contextIsolation: true,
nodeIntegration: false,
webSecurity: false, // Remote URL + preload injection
allowRunningInsecureContent: true,
}
}
```
`setAlwaysOnTop(true, 'screen-saver')` und `setVisibleOnAllWorkspaces(true)` nach dem Erstellen.
## window.foxBridge API
```javascript
window.foxBridge = {
sendMessage(text), // Text an Fox Laravel via IPC
hideHud(), // HUD verstecken
macCommand(cmd), // AppleScript-Befehl ausführen (async, gibt Result zurück)
onFoxAction(callback), // Fox-Aktionen empfangen
onHudShow(callback), // HUD-Show-Event
onHudHide(callback), // HUD-Hide-Event
onStartListening(callback), // Mikrofon-Start-Signal
onPlayAudio(callback), // Audio-URL zum Abspielen
}
```
## Mac-Agent Befehle
Vordefinierte Shortcuts (z.B. `spotify_play`, `mail_open`, `volume_up`) sowie generische Formen:
- `script:<applescript>` — direktes AppleScript
- `open:<url>` — URL im Standardbrowser öffnen
- `app:<name>` — Mac-App öffnen
- `save:<json>` — Datei auf Desktop schreiben
## Wakeword (OpenWakeWord)
- Python 3, `openwakeword`, `pyaudio`, `numpy`, `tflite-runtime`
- Eingebautes Modell: `hey_jarvis` (kein API-Key, kein Training nötig)
- Electron spawnt `python3 python/wakeword.py` als Child-Process
- Auto-Restart nach Absturz (2s Delay)
- Später: eigenes "hey fox" Modell trainierbar
## Laravel HUD — Anpassungsstellen
Diese 3 optionalen Punkte müssen in `fox-hud.blade.php` / HUD-JavaScript hinzugefügt werden:
1. **ESC schließt HUD:**
```javascript
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') window.foxBridge?.hideHud();
});
```
2. **Mac-Aktionen in `onAction()`:**
```javascript
if (payload.action === 'spotify_play') {
await window.foxBridge?.macCommand('spotify_play');
return;
}
// ... weitere Mac-Aktionen
```
3. **Nachricht senden (optional, wenn direkt ohne Livewire):**
```javascript
window.foxBridge?.sendMessage(text);
```
## Deployment
- Dev: `npm start` (Electron lädt fox.pxo.at/hud direkt)
- LaunchAgent `~/Library/LaunchAgents/at.pxo.fox.plist` für Auto-Start beim Login
- `electron-builder` für DMG-Build — später
## Abhängigkeiten
**npm:**
- `electron` ^28
- `axios` ^1.6 (für sendMessage POST)
**Python:**
- `openwakeword`
- `pyaudio`
- `numpy`
- `tflite-runtime`