dulus-bar 0.3.2__tar.gz → 0.4.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 (34) hide show
  1. {dulus_bar-0.3.2 → dulus_bar-0.4.2}/PKG-INFO +4 -4
  2. {dulus_bar-0.3.2 → dulus_bar-0.4.2}/README.md +2 -2
  3. {dulus_bar-0.3.2 → dulus_bar-0.4.2}/dulus_bar/__init__.py +1 -1
  4. {dulus_bar-0.3.2 → dulus_bar-0.4.2}/dulus_bar/agents.py +15 -0
  5. {dulus_bar-0.3.2 → dulus_bar-0.4.2}/dulus_bar/main.py +16 -0
  6. {dulus_bar-0.3.2 → dulus_bar-0.4.2}/dulus_bar/native/macos.py +21 -2
  7. {dulus_bar-0.3.2 → dulus_bar-0.4.2}/dulus_bar/overlay.py +303 -114
  8. {dulus_bar-0.3.2 → dulus_bar-0.4.2}/dulus_bar/server.py +13 -0
  9. dulus_bar-0.4.2/dulus_bar/wrappers/__init__.py +12 -0
  10. dulus_bar-0.4.2/dulus_bar/wrappers/_resolve_dulus.py +32 -0
  11. dulus_bar-0.4.2/dulus_bar/wrappers/_ws_health.py +38 -0
  12. dulus_bar-0.4.2/dulus_bar/wrappers/agent_wrapper.py +32 -0
  13. dulus_bar-0.4.2/dulus_bar/wrappers/base_wrapper.py +487 -0
  14. dulus_bar-0.4.2/dulus_bar/wrappers/claude_wrapper.py +38 -0
  15. dulus_bar-0.4.2/dulus_bar/wrappers/dulus_wrapper.py +155 -0
  16. dulus_bar-0.4.2/dulus_bar/wrappers/paths.py +178 -0
  17. {dulus_bar-0.3.2 → dulus_bar-0.4.2}/dulus_bar.egg-info/PKG-INFO +4 -4
  18. {dulus_bar-0.3.2 → dulus_bar-0.4.2}/dulus_bar.egg-info/SOURCES.txt +8 -0
  19. {dulus_bar-0.3.2 → dulus_bar-0.4.2}/dulus_bar.egg-info/requires.txt +1 -1
  20. {dulus_bar-0.3.2 → dulus_bar-0.4.2}/pyproject.toml +2 -2
  21. {dulus_bar-0.3.2 → dulus_bar-0.4.2}/tests/test_server_hub.py +4 -3
  22. {dulus_bar-0.3.2 → dulus_bar-0.4.2}/LICENSE +0 -0
  23. {dulus_bar-0.3.2 → dulus_bar-0.4.2}/dulus_bar/__main__.py +0 -0
  24. {dulus_bar-0.3.2 → dulus_bar-0.4.2}/dulus_bar/assets/dulus-bird.png +0 -0
  25. {dulus_bar-0.3.2 → dulus_bar-0.4.2}/dulus_bar/macos_native.py +0 -0
  26. {dulus_bar-0.3.2 → dulus_bar-0.4.2}/dulus_bar/native/__init__.py +0 -0
  27. {dulus_bar-0.3.2 → dulus_bar-0.4.2}/dulus_bar/native/base.py +0 -0
  28. {dulus_bar-0.3.2 → dulus_bar-0.4.2}/dulus_bar/native/linux.py +0 -0
  29. {dulus_bar-0.3.2 → dulus_bar-0.4.2}/dulus_bar/native/windows.py +0 -0
  30. {dulus_bar-0.3.2 → dulus_bar-0.4.2}/dulus_bar.egg-info/dependency_links.txt +0 -0
  31. {dulus_bar-0.3.2 → dulus_bar-0.4.2}/dulus_bar.egg-info/entry_points.txt +0 -0
  32. {dulus_bar-0.3.2 → dulus_bar-0.4.2}/dulus_bar.egg-info/top_level.txt +0 -0
  33. {dulus_bar-0.3.2 → dulus_bar-0.4.2}/setup.cfg +0 -0
  34. {dulus_bar-0.3.2 → dulus_bar-0.4.2}/tests/test_macos_native.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dulus-bar
3
- Version: 0.3.2
3
+ Version: 0.4.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
@@ -19,7 +19,7 @@ Classifier: Programming Language :: Python :: 3
19
19
  Requires-Python: >=3.10
20
20
  Description-Content-Type: text/markdown
21
21
  License-File: LICENSE
22
- Requires-Dist: PyQt6>=6.4.0
22
+ Requires-Dist: PySide6>=6.4.0
23
23
  Requires-Dist: websockets>=12.0
24
24
  Requires-Dist: psutil>=5.9.0
25
25
  Requires-Dist: pywin32>=306; sys_platform == "win32"
@@ -47,8 +47,8 @@ Dynamic: license-file
47
47
  </p>
48
48
 
49
49
  <p align="center">
50
- <img src="assets/island-macos.png" alt="Dulus Bar living in the macOS notch" width="85%">
51
- <br><sub><em>Dulus Bar hugging the macOS notch — hover to expand, agents report in live.</em></sub>
50
+ <img src="https://raw.githubusercontent.com/Dulus-Ai/Dulus-bar/main/assets/island.png" alt="Dulus Bar — the floating island with a live agent and an Allow/Deny prompt" width="78%">
51
+ <br><sub><em>Live model + context per agent, and Allow / Deny right on the island — no diving back into a terminal.</em></sub>
52
52
  </p>
53
53
 
54
54
  ---
@@ -16,8 +16,8 @@
16
16
  </p>
17
17
 
18
18
  <p align="center">
19
- <img src="assets/island-macos.png" alt="Dulus Bar living in the macOS notch" width="85%">
20
- <br><sub><em>Dulus Bar hugging the macOS notch — hover to expand, agents report in live.</em></sub>
19
+ <img src="https://raw.githubusercontent.com/Dulus-Ai/Dulus-bar/main/assets/island.png" alt="Dulus Bar — the floating island with a live agent and an Allow/Deny prompt" width="78%">
20
+ <br><sub><em>Live model + context per agent, and Allow / Deny right on the island — no diving back into a terminal.</em></sub>
21
21
  </p>
22
22
 
23
23
  ---
@@ -3,4 +3,4 @@
3
3
  Free, native, no subscription. Windows / macOS (notch-aware) / Linux.
4
4
  """
5
5
 
6
- __version__ = "0.2.0"
6
+ __version__ = "0.4.2"
@@ -40,6 +40,13 @@ _AGENTS: List[AgentStyle] = [
40
40
  AgentStyle("aider", "Aider", "✎", "#22c55e", ("aider",)),
41
41
  AgentStyle("cline", "Cline", "◔", "#0ea5e9", ("cline", "roo")),
42
42
  AgentStyle("ollama", "Ollama", "◍", "#000000", ("ollama", "llama")),
43
+ AgentStyle("opencode", "OpenCode", "◈", "#f97316", ("opencode",)),
44
+ AgentStyle("goose", "Goose", "🪿", "#8b5cf6", ("goose", "block goose")),
45
+ AgentStyle("amp", "Amp", "⚡︎", "#ff2d20", ("amp", "sourcegraph")),
46
+ AgentStyle("crush", "Crush", "♥", "#ec4899", ("crush", "charm")),
47
+ AgentStyle("auggie", "Auggie", "Ⓐ", "#0d9488", ("auggie", "augment")),
48
+ AgentStyle("continue", "Continue", "▶", "#ffde59", ("continue", "cn")),
49
+ AgentStyle("plandex", "Plandex", "⌘", "#84cc16", ("plandex",)),
43
50
  ]
44
51
 
45
52
  _BY_ALIAS: Dict[str, AgentStyle] = {}
@@ -96,6 +103,14 @@ _LAUNCH_COMMANDS: Dict[str, Tuple[str, ...]] = {
96
103
  "grok": ("grok",),
97
104
  "copilot": ("copilot",),
98
105
  "opencode": ("opencode",),
106
+ "goose": ("goose",),
107
+ "amp": ("amp",),
108
+ "crush": ("crush",),
109
+ "auggie": ("auggie",),
110
+ "continue": ("cn", "continue"),
111
+ "plandex": ("plandex",),
112
+ "kimi": ("kimi",),
113
+ "mistral": ("mistral", "codestral"),
99
114
  }
100
115
 
101
116
 
@@ -87,7 +87,23 @@ def _run() -> None:
87
87
  raise
88
88
 
89
89
 
90
+ def _is_already_running(host: str = "127.0.0.1", port: int = 17372) -> bool:
91
+ """Check if a Dulus Bar WebSocket hub is already running."""
92
+ import socket
93
+
94
+ try:
95
+ with socket.create_connection((host, port), timeout=0.25):
96
+ return True
97
+ except Exception:
98
+ return False
99
+
100
+
90
101
  def main():
102
+ # Single-instance guard: if Dulus Bar is already running, avoid opening duplicate overlays
103
+ if _is_already_running():
104
+ print("[dulusbar] Dulus Bar is already running (ws://127.0.0.1:17372 active).", file=sys.stderr)
105
+ return
106
+
91
107
  # Escape the terminal on first launch (unless already detached, or the user
92
108
  # forces a foreground run with DULUS_BAR_FOREGROUND=1 for debugging).
93
109
  if (
@@ -165,21 +165,40 @@ class MacOSBackend(NativeBackend):
165
165
 
166
166
  def open_terminal_running(self, command, title="", cwd=None) -> bool:
167
167
  import shlex
168
+ import tempfile
168
169
 
169
170
  parts = []
170
171
  if cwd:
171
172
  parts.append(f"cd {shlex.quote(str(cwd))}")
172
173
  parts.append(" ".join(shlex.quote(str(c)) for c in command))
173
174
  shell_cmd = " && ".join(parts)
175
+ # Write the command to a temp .sh and tell the terminal to run *that*.
176
+ # Inlining shell_cmd inside AppleScript double quotes breaks as soon as
177
+ # any path or argument contains a double quote or backslash — the
178
+ # terminal would open and immediately close, looking like "nothing
179
+ # started". A script file sidesteps AppleScript quoting entirely.
180
+ script_file = None
181
+ try:
182
+ fd, script_file = tempfile.mkstemp(prefix="dulus-bar-", suffix=".sh")
183
+ with os.fdopen(fd, "w") as f:
184
+ f.write("#!/bin/bash\n")
185
+ if title:
186
+ f.write(f"echo -ne '\\033]0;{title}\\007'\n")
187
+ f.write(shell_cmd + "\n")
188
+ os.chmod(script_file, 0o755)
189
+ except Exception:
190
+ script_file = None
191
+
192
+ run_line = f"bash {shlex.quote(script_file)}" if script_file else shell_cmd
174
193
  # Prefer iTerm if present, else Terminal.
175
194
  script_iterm = (
176
195
  'tell application "iTerm"\n'
177
196
  ' create window with default profile\n'
178
- f' tell current session of current window to write text "{shell_cmd}"\n'
197
+ f' tell current session of current window to write text "{run_line}"\n'
179
198
  ' activate\n'
180
199
  'end tell'
181
200
  )
182
- script_term = f'tell application "Terminal" to do script "{shell_cmd}"\ntell application "Terminal" to activate'
201
+ script_term = f'tell application "Terminal" to do script "{run_line}"\ntell application "Terminal" to activate'
183
202
  for script in (script_term, script_iterm):
184
203
  try:
185
204
  r = subprocess.run(["osascript", "-e", script], capture_output=True, timeout=5)