watchdog
requests
gphoto2; sys_platform != 'win32'
Pillow
av
rembg
onnxruntime
# rembg → pymatting → numba → llvmlite, but pinning the bottom of the
# chain explicitly so a partial / corrupted install doesn't silently
# survive into the PyInstaller bundle. v1.0.171 build shipped without
# `libllvmlite.dylib` because the venv's llvmlite wheel had its dylib
# missing on disk; collect_all('rembg') swallowed the ImportError and
# produced a broken .app that crashed at startup. Spec now explicitly
# collects llvmlite's dylib + fails loudly if absent (see photobooth.spec).
numba
llvmlite
pyudev; sys_platform == 'linux'
pycups; sys_platform == 'linux'
qrcode
pyserial
vpype
vpype-gcode
# Force tomli to install from source (sdist) so we get pure-Python.
# Every recent tomli wheel (2.0+) ships mypyc-compiled, whose hash-named
# C extension (e.g. ddc459050edb75a05942__mypyc.cpython-*-darwin.so)
# gets dropped by PyInstaller's stdlib-overlap dedup. Result without
# this pin: `import vpype_cli` raises ModuleNotFoundError at runtime,
# GcodeNode silently falls back to "vpype not found" via a print()
# (so app.log is silent), the customer sees a misleading
# "could not convert string to float: '.'" preview error.
# `--no-binary tomli` forces pip to build the sdist, which is pure
# Python (no mypyc compilation step).
tomli --no-binary tomli
xmodem
opencv-python
pyaudio
faster-whisper
sounddevice
numpy
scipy
scikit-image

# macOS-specific
pyobjc-framework-CoreWLAN; sys_platform == 'darwin'
pyobjc-framework-Cocoa; sys_platform == 'darwin'

# Web Server Dependencies
fastapi>=0.128.0
uvicorn[standard]>=0.40.0
uvloop>=0.21.0; sys_platform != 'win32'
python-multipart>=0.0.22
websockets>=16.0

# OpenClawd Conversational AI Dependencies
anthropic>=0.18.0
openai>=1.0.0
python-telegram-bot>=20.0
httpx>=0.25.0
certifi>=2023.0.0
aiofiles>=23.0.0
slowapi>=0.1.9
python-dotenv>=1.0.0

# Presentation generation
python-pptx>=1.0.0

# Sharing Node Dependencies
smbprotocol
google-auth-oauthlib
google-api-python-client
dropbox
psutil
# Pinned: esptool's CLI/flash deps (rich_click, intelhex, reedsolo, ...) are
# pulled in transitively and bundled by PyInstaller's collect_all('esptool')
# in photobooth.spec. Pinning keeps the bundled flasher deterministic across
# build hosts so a silent esptool/dep drift can't reach customers.
esptool==5.2.0
