Repository navigation
[4.0.0-beta desktop] Tray deps are not in requirements.txt; frozen app can exit immediately #253
Description
PROBLEM
Desktop UX depends on app/tray.py (macOS rumps menubar, Windows pystray + Pillow).
rumps,pystray, andPilloware not inapp/requirements.txt. Only the workflowpip installs them. Anyone runningpyinstaller build_*.speclocally gets no tray.- Committed
build_mac.specdoes not listtrayorrumpsinhiddenimports, and setsconsole=False. - In
app.py__main__, Flask is started on a daemon thread, thenrun_tray()is supposed to block. If tray import/start fails:
flask_thread = threading.Thread(..., daemon=True)
flask_thread.start()
tray_ok = run_tray(PORT) if run_tray else False
if not tray_ok:
flask_thread.join()If run_tray raises before returning False, or if is_supported() is True but rumps is missing and the except path sets run_tray = None after is_supported was already bound — the process can exit because the only remaining thread is daemon.
- CI Mac build uses
console=Trueand a Dock icon and the menubar, so three UIs appear. That is why the CI build stays alive (Terminal owns the process), not because tray is solid.
Suggested RCA
Tray was added as a desktop-only extra in the workflow, never as a declared dependency. The committed spec was not updated to match tray.py. console=False was copied from the "GUI app" design while tray reliability was still best-effort.
Suggested FIX
# app/requirements-desktop.txt
-r requirements.txt
pyinstaller>=6,<7
rumps>=0.4.0; sys_platform == "darwin"
pystray>=0.19.0; sys_platform == "win32"
Pillow>=10,<12
openai>=1.0.0,<2
Workflow: pip install -r requirements-desktop.txt.
Mac spec: hiddenimports += ['tray', 'rumps'].
Win spec: hiddenimports += ['tray', 'pystray', 'PIL.Image', 'PIL.ImageDraw'].
Keep Flask on a non-daemon thread so a tray failure cannot kill the server:
flask_thread = threading.Thread(
target=lambda: app.run(host="127.0.0.1", port=PORT, debug=False, use_reloader=False),
daemon=False,
name="flask-server",
)Bind 127.0.0.1 in the desktop build (not 0.0.0.0) — it is a local helper, not a LAN server.
Unit tests
# tests/python/test_tray.py
from unittest.mock import patch
import tray
def test_is_supported_on_darwin():
with patch("tray._is_macos", return_value=True), patch("tray._is_windows", return_value=False):
assert tray.is_supported() is True
def test_is_supported_on_linux_is_false():
with patch("tray._is_macos", return_value=False), patch("tray._is_windows", return_value=False):
assert tray.is_supported() is False
def test_run_tray_returns_false_when_rumps_missing():
with patch("tray._is_macos", return_value=True), \
patch("tray._run_macos_tray", side_effect=ImportError("No module named rumps")):
assert tray.run_tray(8080) is False
def test_requirements_desktop_lists_tray_libs():
text = open("app/requirements-desktop.txt").read()
assert "rumps" in text
assert "pystray" in textContext: found on branch release-4.0.0-beta while reviewing standalone macOS .app / Windows .exe packaging. Issues in this batch share the title prefix [4.0.0-beta desktop].
Activity
Fujio-Turner commentedon Sep 15, 2026
Fixed on
release-4.0.0-betavia #263