Add Discord-native hybrid front-end for Jarvis (bot + bridge)
Some checks failed
Release / semantic-release (push) Successful in 59s
tests / Unit tests (Linux, Python 3.11) (push) Successful in 13m45s
Release / build-linux (push) Failing after 7m47s
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

Transform isair/jarvis into a Discord-controlled voice assistant running on
the Ubuntu VNC desktop, keeping the mature ~39k-line Python brain intact.

- bot/ (Node + bun, discord.js): /자비스 slash commands (ephemeral),
  voice channel join + voice receive/playback, pluggable VNC screen broadcast
  (selfbot live / noVNC / screenshot)
- bridge/ (Python, Flask): wraps jarvis STT + run_reply_engine + Piper TTS
  behind a thin localhost HTTP API
- .env.example, scripts/ (start_bridge/start_bot/dev), README rewrite,
  docs/language-comparison.md and docs/vnc-xfce-setup.md

Language decision: hybrid (Python brain + Node/bun Discord layer) because
Discord blocks bot video; native screen broadcast only works via a Node
selfbot library.
This commit is contained in:
javis-bot
2026-06-09 14:51:05 +09:00
parent a5bf8d1826
commit c4abf63f38
308 changed files with 94135 additions and 1 deletions

82
src/jarvis/__init__.py Normal file
View File

@@ -0,0 +1,82 @@
"""
Jarvis Voice Assistant
A modular voice assistant with conversation memory, tool integration,
and natural language processing capabilities.
"""
# =============================================================================
# PyInstaller Windows fix - MUST be at the very top before any audio imports
# =============================================================================
# When bundled with PyInstaller on Windows, sounddevice uses ctypes to locate
# PortAudio. The DLLs are extracted to sys._MEIPASS but won't be found by default.
#
# Python 3.8+ on Windows changed DLL loading behavior - PATH is no longer searched
# for DLLs loaded via ctypes. We must use os.add_dll_directory() instead.
#
# See: https://github.com/pyinstaller/pyinstaller/issues/7065
# See: https://github.com/spatialaudio/python-sounddevice/issues/378
# See: https://docs.python.org/3/whatsnew/3.8.html#ctypes
import os as _os
import sys as _sys
if getattr(_sys, 'frozen', False) and _sys.platform == 'win32':
_meipass = getattr(_sys, '_MEIPASS', None)
if _meipass:
# Method 1: os.add_dll_directory (Python 3.8+, the proper solution)
# This explicitly adds the directory to the DLL search path for ctypes
if hasattr(_os, 'add_dll_directory'):
try:
_os.add_dll_directory(_meipass)
# Also add _sounddevice_data/portaudio-binaries if it exists
_portaudio_path = _os.path.join(_meipass, '_sounddevice_data', 'portaudio-binaries')
if _os.path.isdir(_portaudio_path):
_os.add_dll_directory(_portaudio_path)
except Exception:
pass
# Method 2: Modify PATH (legacy fallback, helps with subprocess spawning)
_path = _os.environ.get('PATH', '')
if _meipass not in _path:
_os.environ['PATH'] = _meipass + _os.pathsep + _path
del _path
del _meipass
del _os, _sys
# =============================================================================
# Suppress HuggingFace symlink cache warning on Windows.
# Most Windows users don't have Developer Mode enabled, so HF falls back to
# copying files instead of symlinking. This is fine — just noisier.
import os as _os
if not _os.environ.get("HF_HUB_DISABLE_SYMLINKS_WARNING"):
_os.environ["HF_HUB_DISABLE_SYMLINKS_WARNING"] = "1"
del _os
from .config import load_settings
def get_version() -> tuple[str, str]:
"""Get the application version and release channel.
Returns:
tuple of (version_string, channel) where channel is 'stable' or 'develop'.
When running from source without a build, returns ('dev-local', 'develop').
"""
try:
from ._version import VERSION, RELEASE_CHANNEL
return VERSION, RELEASE_CHANNEL
except ImportError:
return "dev-local", "develop"
def main() -> None:
"""Lazy entrypoint to avoid importing heavy modules at package import time.
Importing `jarvis.daemon` here prevents it from being added to sys.modules
during package import, which avoids runpy warnings when executing
`python -m jarvis.daemon`.
"""
from .daemon import main as _main
_main()
__all__ = ["main", "load_settings", "get_version"]