#!/usr/bin/env python3 """Audio keep-alive: ping the Tinfoil TEE audio models through localhost LiteLLM so voice mode doesn't pay the ~24s cold-start after idle. Runs INSIDE the gateway container via the Cloudron scheduler addon. Uses the LITELLM_MASTER_KEY already in the container env. TTS-only (STT pings cost $0.01/request each; TTS $0.002 — see docs, keep-alive economics). Silent on success; prints + exits non-zero on failure so scheduler logs capture it. """ import json, os, urllib.request, urllib.error, sys PORT = os.environ.get("PORT", "4000") def master_key(): """The gateway's start.sh generates the master key into /app/data/.master_key and exports LITELLM_MASTER_KEY for the litellm process — scheduler tasks run in a separate process tree, so read the key file directly.""" key = os.environ.get("LITELLM_MASTER_KEY", "") if key: return key try: with open("/app/data/.master_key") as f: return f.read().strip() except OSError: return "" KEY = master_key() if not KEY: print("keepalive: no master key (env or /app/data/.master_key)", file=sys.stderr) sys.exit(1) fail = 0 # TTS warm (voxtral-tts) — $0.002/request (Tinfoil request-priced) req = urllib.request.Request( f"http://127.0.0.1:{PORT}/v1/audio/speech", data=json.dumps({"model": "tinfoil/voxtral-tts", "input": "ok", "voice": "casual_female"}).encode(), method="POST", headers={"Authorization": f"Bearer {KEY}", "Content-Type": "application/json"}) try: urllib.request.urlopen(req, timeout=30) except Exception as e: print(f"keepalive: TTS ping failed: {e}", file=sys.stderr) fail = 1 # STT warm disabled 2026-10-11: $0.01/STT request × 6/hr ≈ $52/mo. Revisit only # with a cheaper warm strategy. sys.exit(fail)