Some checks failed
Release / semantic-release (push) Successful in 20s
tests / Unit tests (Linux, Python 3.11) (push) Failing after 5m19s
Release / build-linux (push) Failing after 7m13s
Release / build-windows (push) Has been cancelled
Release / build-macos (arm64, macos-latest) (push) Has been cancelled
Release / build-macos (x64, macos-15-intel) (push) Has been cancelled
Release / release-main (push) Has been cancelled
Release / release-develop (push) Has been cancelled
A deployment had OLLAMA_INTENT_MODEL=qwen2.5:7b while the chat model was a 4b, so every auxiliary call (intent judge, tool router, place extraction, query decomposition) ran on the bigger, slower model and added latency to each command. Make the .env.example comment state the invariant explicitly.
242 lines
13 KiB
Plaintext
242 lines
13 KiB
Plaintext
# ============================================================================
|
||
# Javis Bot — environment configuration
|
||
# Copy to `.env` and fill in. Never commit your real `.env`.
|
||
# ============================================================================
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# Discord bot (normal bot account) — voice I/O + slash commands
|
||
# ---------------------------------------------------------------------------
|
||
# OPTIONAL — leave BLANK to run in userbot/selfbot mode (a single user account
|
||
# does voice + broadcast; see DISCORD_SELFBOT_TOKEN below). When this is empty
|
||
# and a selfbot token is present, the app runs as a userbot automatically.
|
||
# Only fill this in if you specifically want the legacy normal-bot path.
|
||
# From https://discord.com/developers/applications → your app
|
||
DISCORD_BOT_TOKEN=
|
||
DISCORD_APP_ID=
|
||
# The (single) server this bot serves. Guild-scoped commands appear instantly.
|
||
DISCORD_GUILD_ID=
|
||
# Voice channel used by the stream-test scripts (bot/scripts/stream-test).
|
||
DISCORD_VOICE_CHANNEL_ID=
|
||
# Optional text channel for posting conversation transcripts (blank = disabled).
|
||
DISCORD_TRANSCRIPT_CHANNEL_ID=
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# Brain bridge (Python service in bridge/) — STT + reply engine + TTS
|
||
# ---------------------------------------------------------------------------
|
||
BRIDGE_URL=http://127.0.0.1:8765
|
||
BRIDGE_HOST=127.0.0.1
|
||
BRIDGE_PORT=8765
|
||
JARVIS_BRAIN_ENABLED=1
|
||
JARVIS_TTS_ENABLED=1
|
||
# faster-whisper device/compute. GPU by default (RTX 5050 / sm_120, verified).
|
||
# Falls back to CPU automatically if no GPU is passed to the container.
|
||
WHISPER_DEVICE=cuda
|
||
WHISPER_COMPUTE_TYPE=float16
|
||
# Optional explicit Piper voice model (.onnx). If empty, the jarvis default is used.
|
||
TTS_PIPER_MODEL_PATH=
|
||
# TTS engine: "edge" (default) uses Microsoft Edge TTS, a natural Korean neural
|
||
# voice. Set to "piper" for the offline English voice. NOTE: edge is ONLINE —
|
||
# reply text is sent to Microsoft's servers and needs internet.
|
||
TTS_ENGINE=edge
|
||
# Edge voice + speaking rate. Rate is a percentage (+45% ≈ 1.45×). Korean voices:
|
||
# ko-KR-HyunsuMultilingualNeural (M), ko-KR-InJoonNeural (M), ko-KR-SunHiNeural (F).
|
||
EDGE_TTS_VOICE=ko-KR-HyunsuMultilingualNeural
|
||
EDGE_TTS_RATE=+45%
|
||
# Neural-only by default: if synthesis fails the bridge returns no audio rather
|
||
# than speaking Korean through the English Piper voice. Set to 1 to allow the
|
||
# Piper fallback.
|
||
MELO_FALLBACK_PIPER=0
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# Jarvis brain (Ollama-backed). In Docker these populate the rendered
|
||
# config (docker/jarvis-config.template.json). See src/jarvis/config.py.
|
||
# ---------------------------------------------------------------------------
|
||
# In docker-compose this is overridden to http://ollama:11434 automatically.
|
||
OLLAMA_BASE_URL=http://127.0.0.1:11434
|
||
# qwen2.5:3b — small non-reasoning instruct model. ~2.4GB, runs 100% on the GPU
|
||
# (the 8B offloads ~8% to CPU), warm voice turns ~2-4s vs ~5-7s on 8B. Clean
|
||
# Korean on factual/tool replies; can occasionally leak a trailing CJK phrase on
|
||
# free-form chit-chat. Swap back to qwen3:8b for the strongest tool-calling.
|
||
OLLAMA_CHAT_MODEL=qwen2.5:3b
|
||
# Model for the auxiliary small-model calls: intent judge, tool router, weather
|
||
# place extraction, query decomposition. These are classification/JSON calls,
|
||
# NOT the spoken answer, so a small fast model here cuts 2-3 big-model round
|
||
# trips per command without touching answer quality. BLANK uses the stack
|
||
# default qwen2.5:3b, which ollama-init pulls automatically. Set it equal to
|
||
# OLLAMA_CHAT_MODEL to run everything on one resident model instead (saves VRAM
|
||
# at the cost of slower routing when the chat model is large).
|
||
# NEVER set this LARGER than OLLAMA_CHAT_MODEL: the auxiliary calls would then
|
||
# run on the bigger, slower model and add latency to every command (the exact
|
||
# opposite of the split's purpose). Keep it <= the chat model, blank, or equal.
|
||
OLLAMA_INTENT_MODEL=
|
||
OLLAMA_EMBED_MODEL=nomic-embed-text
|
||
WHISPER_MODEL=small
|
||
|
||
# Lock every reply to one language, e.g. OUTPUT_LANGUAGE=Korean. Leave BLANK to
|
||
# keep the default behaviour of replying in whatever language the user wrote in.
|
||
# A fixed value also suppresses stray characters from other scripts (e.g. the
|
||
# occasional trailing CJK fragment small models leak on free-form chat).
|
||
OUTPUT_LANGUAGE=
|
||
|
||
# Operator instruction folder: every *.md in this dir is appended to the main
|
||
# reply LLM's system prompt (filename order), re-read each turn so edits apply
|
||
# without a rebuild/restart. ./agents is bind-mounted here read-only; only
|
||
# change this to relocate the folder inside the container. See README "운영자 지시문".
|
||
AGENTS_DIR=/app/agents
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# Docker desktop (VNC) — used only by the container image
|
||
# ---------------------------------------------------------------------------
|
||
# Host ports the container publishes the VNC + noVNC servers on. Defaults match
|
||
# the compose file (5901 / 6080); override if the host already uses them.
|
||
VNC_PORT=5901
|
||
NOVNC_PORT=6080
|
||
# VNC viewer password (max 8 chars effective). Watch the screen at localhost:5901.
|
||
# Also used by the broadcast keepalive: TigerVNC only refreshes its framebuffer
|
||
# while a VNC client is attached, so the stream keeps a tiny client connected to
|
||
# avoid a choppy (~1.5 fps) capture. Must match the VNC server's password. If
|
||
# unset, the keepalive falls back to the obfuscated passwd file (VNC_PASSWD_FILE,
|
||
# default ~/.config/tigervnc/passwd).
|
||
VNC_PASSWORD=javis123
|
||
# VNC_PASSWD_FILE=/home/claude/.config/tigervnc/passwd
|
||
# Auto-opened page in the in-container Chrome.
|
||
CHROME_START_URL=about:blank
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# Screen-share + browser mode.
|
||
# true = the bot may go Live (screen-share the VNC desktop) and drive the
|
||
# on-screen browser for real-time info (search / play / read screen).
|
||
# false = no screen share; voice only, real-time info via the Gemini API.
|
||
STREAM_BROWSER=true
|
||
# Optional: profile dir for browser-based Google search in plain text turns
|
||
# (no active broadcast). When set, the search helper opens Chrome against this
|
||
# profile instead of a fresh anonymous one. Sign that profile into Google once
|
||
# (run a real Chrome with --user-data-dir=<this path> and log in) so Google
|
||
# treats later searches as a returning user and does not serve the bot-detection
|
||
# page. Leave blank to use an ephemeral headless session (works only where
|
||
# Google does not challenge it). Use a DEDICATED dir, not your everyday Chrome
|
||
# profile, to avoid the "profile in use" lock while Chrome is open.
|
||
CHROME_USER_DATA_DIR=
|
||
# Gemini auth for real-time info when STREAM_BROWSER=false.
|
||
# oauth = use the Gemini CLI with a Google-account login (no API key).
|
||
# Install once: npm i -g @google/gemini-cli ; then run `gemini` and
|
||
# "Sign in with Google". Uses the CLI's built-in web-search grounding.
|
||
# NOTE (2026-06): Google is blocking personal Google accounts on this
|
||
# path ("This client is no longer supported for Gemini Code Assist for
|
||
# individuals"). Workspace/org accounts may still work; personal
|
||
# accounts should use apikey below instead.
|
||
# apikey = REST path; needs GEMINI_API_KEY below
|
||
# (get one at https://aistudio.google.com/app/apikey). Recommended for
|
||
# personal Google accounts now that individual OAuth login is blocked.
|
||
# Either way, real-time search fail-opens to DDG/Brave/Wikipedia if Gemini is
|
||
# unavailable, so this is optional, not required.
|
||
GEMINI_AUTH=oauth
|
||
GEMINI_API_KEY=
|
||
GEMINI_MODEL=gemini-2.0-flash
|
||
# OAuth login source for Docker. The container mounts this into ~/.gemini.
|
||
# Default (blank) = ./docker/gemini-oauth (project-local, cross-platform). Seed
|
||
# it once: cp -r ~/.gemini/. docker/gemini-oauth/ (copy the whole login state).
|
||
# Or point at an existing host login instead, e.g. GEMINI_OAUTH_DIR=~/.gemini
|
||
GEMINI_OAUTH_DIR=
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# VNC screen broadcast
|
||
# selfbot = real live "Go Live" stream (needs a USER/burner token; ToS risk)
|
||
# novnc = share a noVNC browser link (safe, real-time, not native)
|
||
# screenshot = periodic screenshots to the channel (safe, low fps)
|
||
# none = disabled
|
||
# ---------------------------------------------------------------------------
|
||
STREAM_BACKEND=selfbot
|
||
|
||
# The VNC desktop runs on X display :1 (see docs/vnc-xfce-setup.md)
|
||
VNC_DISPLAY=:1
|
||
VNC_RESOLUTION=1920x1080
|
||
# 1080p60 broadcast. 8 Mbps suits 60fps (YouTube-style 1080p60 sits ~8-12 Mbps);
|
||
# drop to 30/4000 for a lighter stream. Max bitrate is 1.5x this value.
|
||
VNC_FRAMERATE=60
|
||
VNC_BITRATE_KBPS=8000
|
||
|
||
# --- selfbot backend ---
|
||
# A THROWAWAY/burner Discord user account token. NEVER your main account.
|
||
# Using a selfbot violates Discord ToS and can get the account banned.
|
||
DISCORD_SELFBOT_TOKEN=
|
||
# Dedicated burner account for the Go-Live BROADCAST, separate from the
|
||
# conversation account above. REQUIRED in userbot mode for the broadcast to
|
||
# work: Discord allows only one voice presence per account, so the conversation
|
||
# and the broadcast cannot share one account (the broadcaster's voice connection
|
||
# never connects). Leave empty in normal-bot mode (the conversation runs on the
|
||
# bot account, so the selfbot account is already broadcast-only). Both burner
|
||
# accounts must be in the server. Use a second throwaway account, never a main.
|
||
DISCORD_STREAM_TOKEN=
|
||
# Hardware (NVENC) encode for the stream. 1 = use the GPU (recommended for
|
||
# 1080p60), 0 = software x264. Requires an NVIDIA GPU + ffmpeg built with nvenc.
|
||
STREAM_HW=1
|
||
# Capture desktop audio into the broadcast so the stream has sound. 1 = on,
|
||
# 0 = mute. Pulls the PipeWire/Pulse monitor of the default sink; override the
|
||
# source with STREAM_AUDIO_SOURCE (e.g. a specific "<sink>.monitor").
|
||
STREAM_AUDIO=1
|
||
STREAM_AUDIO_SOURCE=@DEFAULT_MONITOR@
|
||
|
||
# --- novnc backend ---
|
||
# e.g. http://192.168.10.9:6080/vnc.html (websockify --web=/usr/share/novnc 6080 localhost:5901)
|
||
NOVNC_URL=
|
||
|
||
# --- screenshot backend ---
|
||
SCREENSHOT_INTERVAL_SEC=5
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# Voice behaviour
|
||
# ---------------------------------------------------------------------------
|
||
# Silence (ms) that marks the end of an utterance before sending to the brain.
|
||
VOICE_SILENCE_MS=800
|
||
|
||
# ===========================================================================
|
||
# Split deployment & cross-platform (Ubuntu + Windows 11)
|
||
# ===========================================================================
|
||
# JARVIS_ROLE selects what this machine runs (see docker/run-if-role.sh):
|
||
# full (default) everything in one container
|
||
# browser ONLY the desktop + Chrome + control-server (driven over the LAN)
|
||
# bot ONLY the bot + bridge + TTS (drives a REMOTE browser)
|
||
JARVIS_ROLE=full
|
||
|
||
# --- GPU per OS: pick the matching compose override via COMPOSE_FILE ---
|
||
# IMPORTANT: the file separator is OS-specific. Linux/macOS use ":" (colon);
|
||
# Windows uses ";" (semicolon), because ":" is taken by the drive letter (C:).
|
||
# Using the wrong one makes Docker treat the whole string as a single missing
|
||
# filename ("...gpu-windows.yml: The system cannot find the file specified").
|
||
# Ubuntu / macOS (nvidia-container-toolkit / CDI):
|
||
# COMPOSE_FILE=docker-compose.yml:docker-compose.gpu-linux.yml
|
||
# Windows 11 (Docker Desktop + WSL2 + NVIDIA) — note the ";" separator:
|
||
# COMPOSE_FILE=docker-compose.yml;docker-compose.gpu-windows.yml
|
||
# Browser-only host (no GPU needed): leave COMPOSE_FILE unset (base only).
|
||
# Default below is the Linux form; Windows users must change ":" to ";" AND
|
||
# swap gpu-linux for gpu-windows. If unsure, comment this out and pass the
|
||
# files explicitly: docker compose -f docker-compose.yml -f <gpu-override> ...
|
||
COMPOSE_FILE=docker-compose.yml:docker-compose.gpu-linux.yml
|
||
|
||
# --- Browser HOST (JARVIS_ROLE=browser) — e.g. this LAN machine ---
|
||
# Expose Chrome control to the internal network (no auth, internal only):
|
||
# CDP_BIND=0.0.0.0
|
||
# BROWSER_CONTROL_BIND=0.0.0.0
|
||
# CDP_PUBLISH_BIND=0.0.0.0
|
||
# Defaults are loopback-only.
|
||
|
||
# --- BOT host (JARVIS_ROLE=bot) — e.g. your PC driving the remote browser ---
|
||
# Point the controlBrowser tool at the browser host's control-server:
|
||
# BROWSER_CONTROL_URL=http://192.168.10.9:8777
|
||
# (Leave BROWSER_CONTROL_URL empty on full/browser layouts.)
|
||
|
||
# --- Models (tune per machine) ---
|
||
# OLLAMA_CHAT_MODEL=qwen2.5:7b # quality (needs ~5GB VRAM + whisper small)
|
||
# OLLAMA_CHAT_MODEL=qwen2.5:3b # speed (fits easily, faster on 8GB GPUs)
|
||
# WHISPER_MODEL=small # small frees VRAM for a bigger LLM; medium=more accurate
|
||
# STT_BEAM_SIZE=5 # beam search (5) > greedy (1) for accuracy; lower for speed
|
||
# MELO_DEVICE=cuda # cpu if no GPU on the bot host
|
||
|
||
# --- Settings web UI (http://localhost:8765/settings on the bot host) ---
|
||
# To reach it, expose the bridge to the host loopback:
|
||
# BRIDGE_HOST=0.0.0.0
|
||
# SETTINGS_PUBLISH_BIND=127.0.0.1 # 0.0.0.0 to allow LAN access (no auth)
|
||
# Change models / STT / TTS speed / language / LLM instructions live; "적용"
|
||
# restarts the bridge + TTS worker so changes take effect.
|