Skip to content

feat: desktop app + Ollama discovery + voice/keychain fixes#51

Closed
UmarFarooq75 wants to merge 1 commit into
mainfrom
dev
Closed

feat: desktop app + Ollama discovery + voice/keychain fixes#51
UmarFarooq75 wants to merge 1 commit into
mainfrom
dev

Conversation

@UmarFarooq75

Copy link
Copy Markdown
Collaborator

Summary

  • Desktop app (Tauri): vault passphrase persisted in OS keychain (macOS / Windows / Linux), auto-unlock on launch, Skip button on boot; frontend drives the unlock flow so VAULT_PASSPHRASE reaches Daemora on first spawn.
  • Ollama: models discovered live from `${OLLAMA_BASE_URL}/api/tags` instead of a hardcoded preset list; URL configurable in Settings; picker shows only what the user has pulled. Switched to `ollama-ai-provider-v2` (AI SDK v5+ spec).
  • Voice: TaskRunner force-streams voice tasks so TTS actually gets tokens; Groq TTS uses `livekit-plugins-groq` with an explicit aiohttp session; local-speaker is opt-in via `DAEMORA_LOCAL_SPEAKER=1` so browser users don't get echo; model-implied provider overrides stale `DAEMORA_TTS_PROVIDER` to prevent Orpheus/"diana" being dispatched to OpenAI.
  • UI: Replaced every `window.confirm()` with Radix `AlertDialog` (native dialogs are blocked in Tauri WKWebView); Settings STT/TTS/voice dropdowns filter by configured provider keys; trash-can delete now actually re-fetches settings.
  • Sidecar: screen-size cached so /health doesn't trigger macOS screen-recording TCC on every poll; file logging at `~/.daemora/sidecar.log`.
  • Housekeeping: `daemora-ui/dist/` gitignored; DELETE /api/settings/:key endpoint; strict voice-mode system prompt.

Test plan

  • Install Daemora.app from debug bundle on a clean Mac; first launch shows vault prompt, second launch auto-unlocks from keychain
  • Pull any Ollama model, Settings → Default Model shows it without restart (auto-refresh every 60s)
  • Voice with Groq Orpheus + browser — no echo, no "stream_format" 400, TTS audible
  • Delete an API key from Settings — AlertDialog appears, key disappears after confirm
  • Change TTS model in Settings — provider auto-resolves from model name, no 400s
  • Chat on Ollama model under AI SDK 5 — no "Unsupported model version v1" crash

Comment thread desktop/sidecar/daemora_sidecar/main.py Outdated

@app.post("/desktop/click", dependencies=[Depends(verify_token)])
def http_click(req: ClickReq) -> dict:
return handle(desktop.mouse_click, req.x, req.y, req.button, req.clicks)
Comment thread desktop/sidecar/daemora_sidecar/main.py Outdated

@app.post("/desktop/move", dependencies=[Depends(verify_token)])
def http_move(req: MoveReq) -> dict:
return handle(desktop.mouse_move, req.x, req.y, req.duration)
Comment thread desktop/sidecar/daemora_sidecar/main.py Outdated

@app.post("/desktop/type", dependencies=[Depends(verify_token)])
def http_type(req: TypeReq) -> dict:
return handle(desktop.type_text, req.text, req.interval)
Comment thread desktop/sidecar/daemora_sidecar/main.py Outdated

@app.post("/desktop/keypress", dependencies=[Depends(verify_token)])
def http_key(req: KeyReq) -> dict:
return handle(desktop.press_key, req.key)
Comment thread desktop/sidecar/daemora_sidecar/main.py Outdated

@app.post("/desktop/combo", dependencies=[Depends(verify_token)])
def http_combo(req: ComboReq) -> dict:
return handle(desktop.key_combo, req.keys)
Comment thread desktop/sidecar/daemora_sidecar/main.py Outdated

@app.post("/desktop/scroll", dependencies=[Depends(verify_token)])
def http_scroll(req: ScrollReq) -> dict:
return handle(desktop.scroll, req.dx, req.dy)
Comment thread desktop/sidecar/daemora_sidecar/main.py Outdated

@app.post("/desktop/screenshot", dependencies=[Depends(verify_token)])
def http_screenshot(req: ScreenshotReq) -> dict:
return handle(desktop.screenshot, req.region)
Comment thread desktop/sidecar/daemora_sidecar/main.py Outdated

@app.get("/desktop/windows", dependencies=[Depends(verify_token)])
def http_list_windows() -> dict:
return handle(desktop.list_windows)
Comment thread desktop/sidecar/daemora_sidecar/main.py Outdated

@app.post("/desktop/focus", dependencies=[Depends(verify_token)])
def http_focus(req: FocusReq) -> dict:
return handle(desktop.focus_window, req.name)
Comment thread desktop/sidecar/daemora_sidecar/main.py Outdated
Comment on lines +146 to +149
return {
"running": running,
"error": _voice_error,
}
Comment thread src/index.js Outdated
canUpdateOwnMetadata: true,
},
};
const b64url = (buf) => Buffer.from(buf).toString("base64").replace(/=+$/, "").replace(/\+/g, "-").replace(/\//g, "_");
Comment thread src/index.js Outdated
const headerB = b64url(JSON.stringify(header));
const payloadB = b64url(JSON.stringify(payload));
const toSign = `${headerB}.${payloadB}`;
const sig = createHmac("sha256", apiSecret).update(toSign).digest();
Includes session fixes:
- Vertex SA auth via env vars (no hardcoded user paths)
- Channels boot after vault unlock (fix silent secrets-missing skip)
- Token refresh: 30 min sweep + per-account early-refresh timers
- Vault stays unlocked until process restart
- .env loaded via Node loadEnvFile at first import
- README: removed stale daemora channels CLI references
- .gitignore: credentials/secrets/scratch patterns
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants