# --------------------------------------------------------------------------- # Discord Agent — environment configuration # Copy to .env and fill in. .env is gitignored; never commit real secrets. # Values are validated at startup by packages/shared loadConfig(). # --------------------------------------------------------------------------- # --- Discord --------------------------------------------------------------- # Bot token from the Discord Developer Portal (Bot -> Reset Token). DISCORD_TOKEN= # Application (client) ID — used to register slash commands. DISCORD_APP_ID= # The single private guild (server) this agent operates in. DISCORD_GUILD_ID= # Comma-separated voice channel IDs that are armed for auto-record. # Empty = no channels auto-record until armed via slash command. DISCORD_AUTORECORD_CHANNEL_IDS= # Optional: comma-separated role/user IDs that trigger auto-join when they # join an armed channel. Empty = trigger on any non-bot human (>=1 present). DISCORD_TRIGGER_ROLE_IDS= DISCORD_TRIGGER_USER_IDS= # --- Local inference (Ollama, OpenAI-compatible endpoint on the Spark) ------ # DGX Spark = tailnet host gx10-4210 (100.77.83.28). Use the 100.x IP, not a # MagicDNS name (tailnet DNS is currently degraded). NOTE: expose Ollama on the # Spark first (OLLAMA_HOST=0.0.0.0 ollama serve) — it binds 127.0.0.1 by default. OLLAMA_BASE_URL=http://100.77.83.28:11434/v1 # Small, fast model for interactive text (DMs / channel replies). OLLAMA_INTERACTIVE_MODEL=qwen2.5:7b # Large model for post-call batch summarization. OLLAMA_BATCH_MODEL=qwen2.5:32b # Optional API key if the endpoint is protected (Ollama ignores it by default). OLLAMA_API_KEY= # --- Transcription (faster-whisper) ---------------------------------------- # Whisper model size/name loaded by the processing service. WHISPER_MODEL=large-v3 # Compute type for CTranslate2 (e.g. float16, int8_float16, int8). WHISPER_COMPUTE_TYPE=float16 # OpenAI-compatible faster-whisper HTTP service (POST {base}/audio/transcriptions). # Read directly by packages/processing. On the Spark (gx10-4210 / 100.77.83.28); # stand this service up on :8000 — it is not yet running. WHISPER_BASE_URL=http://100.77.83.28:8000/v1 # Optional language hint (ISO-639-1). Empty = auto-detect. WHISPER_LANGUAGE= # Optional bearer token if the STT endpoint is protected. WHISPER_API_KEY= # --- Processing service ---------------------------------------------------- # How often the batch watcher polls the storage dir for ready-to-process calls. PROCESSING_POLL_INTERVAL_MS=5000 # A call left transcribing/summarizing longer than this (ms) is treated as a # crashed run and re-enqueued. Must exceed worst-case processing time. 15 min. PROCESSING_STALE_LEASE_MS=900000 # --- Email (provider-agnostic IMAP read + SMTP send) ----------------------- IMAP_HOST= IMAP_PORT=993 IMAP_USER= IMAP_PASSWORD= IMAP_TLS=true SMTP_HOST= SMTP_PORT=465 SMTP_USER= SMTP_PASSWORD= SMTP_SECURE=true # From address the agent sends as. AGENT_EMAIL_FROM= # Recipient for post-call summary emails (FR-19). Optional; defaults to # AGENT_EMAIL_FROM (the agent's own inbox) when email is configured. SUMMARY_EMAIL_TO= # --- Storage & retention --------------------------------------------------- # Base directory for per-call data (audio tracks, manifest, transcript, summary). STORAGE_DIR=./data/calls # Days to retain raw audio before auto-purge. Transcripts/summaries kept indefinitely. AUDIO_RETENTION_DAYS=7 # Days to retain video.mp4 before auto-purge (video is large + sensitive). # Empty = fall back to AUDIO_RETENTION_DAYS. Timecoded transcript is kept. VIDEO_RETENTION_DAYS= # --- Video recording (OBS, optional) --------------------------------------- # Optional "Path A" video capture: the bot drives a participant-side OBS over # OBS WebSocket and (optionally) moves an already-connected recorder account # into/out of the call. OFF by default — with OBS_ENABLED=false behavior is # byte-for-byte identical to audio-only. See docs/DEPLOY.md §9. When enabled, # OBS_WEBSOCKET_URL is required; the rest are optional (partial config is fine). OBS_ENABLED=false # OBS WebSocket v5 URL. Deployment: OBS runs on THIS workstation alongside the # capture service and the recorder/context-backdrop client, so localhost is # correct. (Only a remote OBS needs a tailnet MagicDNS name / 100.x.y.z.) OBS_WEBSOCKET_URL=ws://127.0.0.1:4455 # OBS WebSocket auth (Tools -> WebSocket Server Settings). Empty = no auth. OBS_WEBSOCKET_PASSWORD= # Folder OBS writes recordings to. Local path since OBS is co-located here — the # capture service copies the finished recording into the call dir as video.mp4. # Empty = reference OBS's own path instead of copying. OBS_OUTPUT_DIR=/home/bob/Videos/discord-agent # Discord user ID of the parked recorder account. Set = the bot moves it into the # call and back to the lobby (requires the bot's Move Members permission). The # account must already be running a client and voice-connected — a bot cannot # originate its connection. Empty = no recorder move (OBS-only). RECORDER_USER_ID= # Voice channel the recorder account is parked in / moved back to on stop. RECORDER_LOBBY_CHANNEL_ID= # --- Runtime --------------------------------------------------------------- LOG_LEVEL=info