dulus-bar 0.3.1__tar.gz → 0.3.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. {dulus_bar-0.3.1 → dulus_bar-0.3.2}/PKG-INFO +1 -1
  2. dulus_bar-0.3.2/dulus_bar/main.py +108 -0
  3. {dulus_bar-0.3.1 → dulus_bar-0.3.2}/dulus_bar/overlay.py +12 -1
  4. {dulus_bar-0.3.1 → dulus_bar-0.3.2}/dulus_bar.egg-info/PKG-INFO +1 -1
  5. {dulus_bar-0.3.1 → dulus_bar-0.3.2}/pyproject.toml +1 -1
  6. dulus_bar-0.3.1/dulus_bar/main.py +0 -42
  7. {dulus_bar-0.3.1 → dulus_bar-0.3.2}/LICENSE +0 -0
  8. {dulus_bar-0.3.1 → dulus_bar-0.3.2}/README.md +0 -0
  9. {dulus_bar-0.3.1 → dulus_bar-0.3.2}/dulus_bar/__init__.py +0 -0
  10. {dulus_bar-0.3.1 → dulus_bar-0.3.2}/dulus_bar/__main__.py +0 -0
  11. {dulus_bar-0.3.1 → dulus_bar-0.3.2}/dulus_bar/agents.py +0 -0
  12. {dulus_bar-0.3.1 → dulus_bar-0.3.2}/dulus_bar/assets/dulus-bird.png +0 -0
  13. {dulus_bar-0.3.1 → dulus_bar-0.3.2}/dulus_bar/macos_native.py +0 -0
  14. {dulus_bar-0.3.1 → dulus_bar-0.3.2}/dulus_bar/native/__init__.py +0 -0
  15. {dulus_bar-0.3.1 → dulus_bar-0.3.2}/dulus_bar/native/base.py +0 -0
  16. {dulus_bar-0.3.1 → dulus_bar-0.3.2}/dulus_bar/native/linux.py +0 -0
  17. {dulus_bar-0.3.1 → dulus_bar-0.3.2}/dulus_bar/native/macos.py +0 -0
  18. {dulus_bar-0.3.1 → dulus_bar-0.3.2}/dulus_bar/native/windows.py +0 -0
  19. {dulus_bar-0.3.1 → dulus_bar-0.3.2}/dulus_bar/server.py +0 -0
  20. {dulus_bar-0.3.1 → dulus_bar-0.3.2}/dulus_bar.egg-info/SOURCES.txt +0 -0
  21. {dulus_bar-0.3.1 → dulus_bar-0.3.2}/dulus_bar.egg-info/dependency_links.txt +0 -0
  22. {dulus_bar-0.3.1 → dulus_bar-0.3.2}/dulus_bar.egg-info/entry_points.txt +0 -0
  23. {dulus_bar-0.3.1 → dulus_bar-0.3.2}/dulus_bar.egg-info/requires.txt +0 -0
  24. {dulus_bar-0.3.1 → dulus_bar-0.3.2}/dulus_bar.egg-info/top_level.txt +0 -0
  25. {dulus_bar-0.3.1 → dulus_bar-0.3.2}/setup.cfg +0 -0
  26. {dulus_bar-0.3.1 → dulus_bar-0.3.2}/tests/test_macos_native.py +0 -0
  27. {dulus_bar-0.3.1 → dulus_bar-0.3.2}/tests/test_server_hub.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dulus-bar
3
- Version: 0.3.1
3
+ Version: 0.3.2
4
4
  Summary: Dulus Bar — a cross-platform Dynamic Island for your AI agents (Windows / macOS / Linux)
5
5
  Author-email: Dulus <dev@dulus.ai>
6
6
  License: MIT
@@ -0,0 +1,108 @@
1
+ """Entry point for Dulus Bar.
2
+
3
+ Supports both:
4
+ python -m dulus_bar
5
+ python dulus_bar/main.py
6
+
7
+ A menu-bar / tray app must never hold a terminal hostage. When launched from a
8
+ console (``dulusbar`` / ``dulus-bar`` in a shell) we relaunch ourselves detached
9
+ with no console and return immediately, so the prompt comes straight back and
10
+ the app lives in the tray / status bar.
11
+ """
12
+
13
+ import os
14
+ import sys
15
+
16
+
17
+ def _launched_from_console() -> bool:
18
+ """True when we're attached to a terminal we should escape from."""
19
+ if os.name == "nt":
20
+ try:
21
+ import ctypes
22
+ return bool(ctypes.windll.kernel32.GetConsoleWindow())
23
+ except Exception:
24
+ return False
25
+ try:
26
+ return bool(sys.stdout and sys.stdout.isatty())
27
+ except Exception:
28
+ return False
29
+
30
+
31
+ def _relaunch_detached() -> bool:
32
+ """Relaunch in the background with no console. Returns True on success."""
33
+ import subprocess
34
+
35
+ env = dict(os.environ)
36
+ env["DULUS_BAR_DETACHED"] = "1"
37
+ argv = [sys.executable, "-m", "dulus_bar"]
38
+ try:
39
+ if os.name == "nt":
40
+ DETACHED_PROCESS = 0x00000008
41
+ CREATE_NO_WINDOW = 0x08000000
42
+ subprocess.Popen(
43
+ argv,
44
+ env=env,
45
+ creationflags=DETACHED_PROCESS | CREATE_NO_WINDOW,
46
+ stdin=subprocess.DEVNULL,
47
+ stdout=subprocess.DEVNULL,
48
+ stderr=subprocess.DEVNULL,
49
+ close_fds=True,
50
+ )
51
+ else:
52
+ subprocess.Popen(
53
+ argv,
54
+ env=env,
55
+ start_new_session=True,
56
+ stdin=subprocess.DEVNULL,
57
+ stdout=subprocess.DEVNULL,
58
+ stderr=subprocess.DEVNULL,
59
+ )
60
+ return True
61
+ except Exception:
62
+ return False
63
+
64
+
65
+ def _run() -> None:
66
+ try:
67
+ from dulus_bar.macos_native import run_native, should_use_native
68
+
69
+ if should_use_native():
70
+ try:
71
+ raise SystemExit(run_native())
72
+ except Exception as exc:
73
+ if os.environ.get("DULUS_BAR_NATIVE_REQUIRED", "0") in {"1", "true", "yes"}:
74
+ raise
75
+ print(
76
+ f"[dulusbar] native macOS surface unavailable ({exc}); using Qt fallback",
77
+ file=sys.stderr,
78
+ )
79
+
80
+ from dulus_bar.overlay import run_overlay
81
+
82
+ run_overlay()
83
+ except SystemExit:
84
+ raise
85
+ except Exception as exc:
86
+ print(f"Dulus Bar crashed: {exc}", file=sys.stderr)
87
+ raise
88
+
89
+
90
+ def main():
91
+ # Escape the terminal on first launch (unless already detached, or the user
92
+ # forces a foreground run with DULUS_BAR_FOREGROUND=1 for debugging).
93
+ if (
94
+ os.environ.get("DULUS_BAR_DETACHED") != "1"
95
+ and os.environ.get("DULUS_BAR_FOREGROUND", "0") not in {"1", "true", "yes"}
96
+ and _launched_from_console()
97
+ ):
98
+ if _relaunch_detached():
99
+ return # the detached copy took over — free this terminal
100
+ _run()
101
+
102
+
103
+ if __name__ == "__main__":
104
+ if __package__ is None:
105
+ # Running directly (python dulus_bar/main.py): add project root to path.
106
+ project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
107
+ sys.path.insert(0, project_root)
108
+ main()
@@ -423,7 +423,18 @@ class DulusBarOverlay(QMainWindow):
423
423
  self.pill.setGraphicsEffect(shadow)
424
424
 
425
425
  def _build_toast(self) -> None:
426
- self.toast = QWidget(self)
426
+ # Top-level window, NOT a child of the island. A child is clipped to the
427
+ # tiny island window and never shows — which is why Allow/Deny was
428
+ # invisible. As its own frameless, always-on-top window the permission
429
+ # prompt floats below the pill anywhere on screen.
430
+ self.toast = QWidget(None)
431
+ self.toast.setWindowFlags(
432
+ Qt.WindowType.FramelessWindowHint
433
+ | Qt.WindowType.WindowStaysOnTopHint
434
+ | Qt.WindowType.Tool
435
+ | Qt.WindowType.NoDropShadowWindowHint
436
+ )
437
+ self.toast.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
427
438
  self.toast.setObjectName("toast")
428
439
  self.toast.setStyleSheet(
429
440
  f"#toast {{ background-color: {BG_HOVER}; border: 1px solid {BORDER_HOVER}; border-radius: 16px; }}"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dulus-bar
3
- Version: 0.3.1
3
+ Version: 0.3.2
4
4
  Summary: Dulus Bar — a cross-platform Dynamic Island for your AI agents (Windows / macOS / Linux)
5
5
  Author-email: Dulus <dev@dulus.ai>
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "dulus-bar"
7
- version = "0.3.1"
7
+ version = "0.3.2"
8
8
  description = "Dulus Bar — a cross-platform Dynamic Island for your AI agents (Windows / macOS / Linux)"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -1,42 +0,0 @@
1
- """Entry point for Dulus Bar.
2
-
3
- Supports both:
4
- python -m dulus_bar
5
- python dulus_bar/main.py
6
- """
7
-
8
- import os
9
- import sys
10
-
11
-
12
- def main():
13
- try:
14
- from dulus_bar.macos_native import run_native, should_use_native
15
-
16
- if should_use_native():
17
- try:
18
- raise SystemExit(run_native())
19
- except Exception as exc:
20
- if os.environ.get("DULUS_BAR_NATIVE_REQUIRED", "0") in {"1", "true", "yes"}:
21
- raise
22
- print(
23
- f"[dulusbar] native macOS surface unavailable ({exc}); using Qt fallback",
24
- file=sys.stderr,
25
- )
26
-
27
- from dulus_bar.overlay import run_overlay
28
-
29
- run_overlay()
30
- except SystemExit:
31
- raise
32
- except Exception as exc:
33
- print(f"Dulus Bar crashed: {exc}", file=sys.stderr)
34
- raise
35
-
36
-
37
- if __name__ == "__main__":
38
- if __package__ is None:
39
- # Running directly (python dulus_bar/main.py): add project root to path.
40
- project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
41
- sys.path.insert(0, project_root)
42
- main()
File without changes
File without changes
File without changes
File without changes
File without changes