dulus 0.2.26__tar.gz → 0.2.27__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 (164) hide show
  1. {dulus-0.2.26/dulus.egg-info → dulus-0.2.27}/PKG-INFO +2 -2
  2. {dulus-0.2.26 → dulus-0.2.27}/README.md +1 -1
  3. {dulus-0.2.26 → dulus-0.2.27}/docs/news.md +2 -0
  4. {dulus-0.2.26 → dulus-0.2.27/dulus.egg-info}/PKG-INFO +2 -2
  5. {dulus-0.2.26 → dulus-0.2.27}/dulus.py +30 -2
  6. {dulus-0.2.26 → dulus-0.2.27}/pyproject.toml +1 -1
  7. {dulus-0.2.26 → dulus-0.2.27}/LICENSE +0 -0
  8. {dulus-0.2.26 → dulus-0.2.27}/MANIFEST.in +0 -0
  9. {dulus-0.2.26 → dulus-0.2.27}/agent.py +0 -0
  10. {dulus-0.2.26 → dulus-0.2.27}/backend/__init__.py +0 -0
  11. {dulus-0.2.26 → dulus-0.2.27}/backend/compressor.py +0 -0
  12. {dulus-0.2.26 → dulus-0.2.27}/backend/context.py +0 -0
  13. {dulus-0.2.26 → dulus-0.2.27}/backend/githook.py +0 -0
  14. {dulus-0.2.26 → dulus-0.2.27}/backend/marketplace.py +0 -0
  15. {dulus-0.2.26 → dulus-0.2.27}/backend/mempalace_bridge.py +0 -0
  16. {dulus-0.2.26 → dulus-0.2.27}/backend/personas.py +0 -0
  17. {dulus-0.2.26 → dulus-0.2.27}/backend/plugins.py +0 -0
  18. {dulus-0.2.26 → dulus-0.2.27}/backend/server.py +0 -0
  19. {dulus-0.2.26 → dulus-0.2.27}/backend/tasks.py +0 -0
  20. {dulus-0.2.26 → dulus-0.2.27}/batch_api.py +0 -0
  21. {dulus-0.2.26 → dulus-0.2.27}/checkpoint/__init__.py +0 -0
  22. {dulus-0.2.26 → dulus-0.2.27}/checkpoint/hooks.py +0 -0
  23. {dulus-0.2.26 → dulus-0.2.27}/checkpoint/store.py +0 -0
  24. {dulus-0.2.26 → dulus-0.2.27}/checkpoint/types.py +0 -0
  25. {dulus-0.2.26 → dulus-0.2.27}/claude_code_watcher.py +0 -0
  26. {dulus-0.2.26 → dulus-0.2.27}/clipboard_utils.py +0 -0
  27. {dulus-0.2.26 → dulus-0.2.27}/cloudsave.py +0 -0
  28. {dulus-0.2.26 → dulus-0.2.27}/common.py +0 -0
  29. {dulus-0.2.26 → dulus-0.2.27}/compaction.py +0 -0
  30. {dulus-0.2.26 → dulus-0.2.27}/config.py +0 -0
  31. {dulus-0.2.26 → dulus-0.2.27}/context.py +0 -0
  32. {dulus-0.2.26 → dulus-0.2.27}/data/__init__.py +0 -0
  33. {dulus-0.2.26 → dulus-0.2.27}/data/active_persona.json +0 -0
  34. {dulus-0.2.26 → dulus-0.2.27}/data/context.json +0 -0
  35. {dulus-0.2.26 → dulus-0.2.27}/data/marketplace.json +0 -0
  36. {dulus-0.2.26 → dulus-0.2.27}/data/personas.json +0 -0
  37. {dulus-0.2.26 → dulus-0.2.27}/data/plugins/__init__.py +0 -0
  38. {dulus-0.2.26 → dulus-0.2.27}/data/plugins/composio/__init__.py +0 -0
  39. {dulus-0.2.26 → dulus-0.2.27}/data/plugins/composio/composio_plugin/__init__.py +0 -0
  40. {dulus-0.2.26 → dulus-0.2.27}/data/plugins/composio/composio_plugin/session_manager.py +0 -0
  41. {dulus-0.2.26 → dulus-0.2.27}/data/plugins/composio/composio_plugin/tool_generator.py +0 -0
  42. {dulus-0.2.26 → dulus-0.2.27}/data/plugins/composio/plugin.json +0 -0
  43. {dulus-0.2.26 → dulus-0.2.27}/data/plugins/composio/plugin_tool.py +0 -0
  44. {dulus-0.2.26 → dulus-0.2.27}/data/tasks.json +0 -0
  45. {dulus-0.2.26 → dulus-0.2.27}/docs/README.md +0 -0
  46. {dulus-0.2.26 → dulus-0.2.27}/docs/__init__.py +0 -0
  47. {dulus-0.2.26 → dulus-0.2.27}/docs/api.html +0 -0
  48. {dulus-0.2.26 → dulus-0.2.27}/docs/architecture.md +0 -0
  49. {dulus-0.2.26 → dulus-0.2.27}/docs/azure-speech-template.json +0 -0
  50. {dulus-0.2.26 → dulus-0.2.27}/docs/dashboard/index.html +0 -0
  51. {dulus-0.2.26 → dulus-0.2.27}/docs/divider.svg +0 -0
  52. {dulus-0.2.26 → dulus-0.2.27}/docs/generate.py +0 -0
  53. {dulus-0.2.26 → dulus-0.2.27}/docs/hero.svg +0 -0
  54. {dulus-0.2.26 → dulus-0.2.27}/docs/index.html +0 -0
  55. {dulus-0.2.26 → dulus-0.2.27}/docs/nvidia-models.svg +0 -0
  56. {dulus-0.2.26 → dulus-0.2.27}/docs/particle-playground.html +0 -0
  57. {dulus-0.2.26 → dulus-0.2.27}/docs/personas/index.html +0 -0
  58. {dulus-0.2.26 → dulus-0.2.27}/docs/poetry-banner.png +0 -0
  59. {dulus-0.2.26 → dulus-0.2.27}/docs/preview.html +0 -0
  60. {dulus-0.2.26 → dulus-0.2.27}/docs/sec-agents.svg +0 -0
  61. {dulus-0.2.26 → dulus-0.2.27}/docs/sec-brainstorm.svg +0 -0
  62. {dulus-0.2.26 → dulus-0.2.27}/docs/sec-bridges.svg +0 -0
  63. {dulus-0.2.26 → dulus-0.2.27}/docs/sec-features.svg +0 -0
  64. {dulus-0.2.26 → dulus-0.2.27}/docs/sec-freetier.svg +0 -0
  65. {dulus-0.2.26 → dulus-0.2.27}/docs/sec-memory.svg +0 -0
  66. {dulus-0.2.26 → dulus-0.2.27}/docs/sec-models.svg +0 -0
  67. {dulus-0.2.26 → dulus-0.2.27}/docs/sec-perms.svg +0 -0
  68. {dulus-0.2.26 → dulus-0.2.27}/docs/sec-plugins.svg +0 -0
  69. {dulus-0.2.26 → dulus-0.2.27}/docs/sec-quickstart.svg +0 -0
  70. {dulus-0.2.26 → dulus-0.2.27}/docs/sec-ssj.svg +0 -0
  71. {dulus-0.2.26 → dulus-0.2.27}/docs/spinners.svg +0 -0
  72. {dulus-0.2.26 → dulus-0.2.27}/docs/split-pane.svg +0 -0
  73. {dulus-0.2.26 → dulus-0.2.27}/docs/terminal-boot.svg +0 -0
  74. {dulus-0.2.26 → dulus-0.2.27}/docs/uploads/particle-playground.html +0 -0
  75. {dulus-0.2.26 → dulus-0.2.27}/dulus.egg-info/SOURCES.txt +0 -0
  76. {dulus-0.2.26 → dulus-0.2.27}/dulus.egg-info/dependency_links.txt +0 -0
  77. {dulus-0.2.26 → dulus-0.2.27}/dulus.egg-info/entry_points.txt +0 -0
  78. {dulus-0.2.26 → dulus-0.2.27}/dulus.egg-info/requires.txt +0 -0
  79. {dulus-0.2.26 → dulus-0.2.27}/dulus.egg-info/top_level.txt +0 -0
  80. {dulus-0.2.26 → dulus-0.2.27}/dulus_gui.py +0 -0
  81. {dulus-0.2.26 → dulus-0.2.27}/dulus_mcp/__init__.py +0 -0
  82. {dulus-0.2.26 → dulus-0.2.27}/dulus_mcp/client.py +0 -0
  83. {dulus-0.2.26 → dulus-0.2.27}/dulus_mcp/config.py +0 -0
  84. {dulus-0.2.26 → dulus-0.2.27}/dulus_mcp/tools.py +0 -0
  85. {dulus-0.2.26 → dulus-0.2.27}/dulus_mcp/types.py +0 -0
  86. {dulus-0.2.26 → dulus-0.2.27}/gui/__init__.py +0 -0
  87. {dulus-0.2.26 → dulus-0.2.27}/gui/agent_bridge.py +0 -0
  88. {dulus-0.2.26 → dulus-0.2.27}/gui/chat_widget.py +0 -0
  89. {dulus-0.2.26 → dulus-0.2.27}/gui/main_window.py +0 -0
  90. {dulus-0.2.26 → dulus-0.2.27}/gui/personas.py +0 -0
  91. {dulus-0.2.26 → dulus-0.2.27}/gui/session_utils.py +0 -0
  92. {dulus-0.2.26 → dulus-0.2.27}/gui/settings_dialog.py +0 -0
  93. {dulus-0.2.26 → dulus-0.2.27}/gui/sidebar.py +0 -0
  94. {dulus-0.2.26 → dulus-0.2.27}/gui/tasks_view.py +0 -0
  95. {dulus-0.2.26 → dulus-0.2.27}/gui/themes.py +0 -0
  96. {dulus-0.2.26 → dulus-0.2.27}/gui/tool_panel.py +0 -0
  97. {dulus-0.2.26 → dulus-0.2.27}/input.py +0 -0
  98. {dulus-0.2.26 → dulus-0.2.27}/license_manager.py +0 -0
  99. {dulus-0.2.26 → dulus-0.2.27}/memory/__init__.py +0 -0
  100. {dulus-0.2.26 → dulus-0.2.27}/memory/audit.py +0 -0
  101. {dulus-0.2.26 → dulus-0.2.27}/memory/consolidator.py +0 -0
  102. {dulus-0.2.26 → dulus-0.2.27}/memory/context.py +0 -0
  103. {dulus-0.2.26 → dulus-0.2.27}/memory/offload.py +0 -0
  104. {dulus-0.2.26 → dulus-0.2.27}/memory/palace.py +0 -0
  105. {dulus-0.2.26 → dulus-0.2.27}/memory/scan.py +0 -0
  106. {dulus-0.2.26 → dulus-0.2.27}/memory/sessions.py +0 -0
  107. {dulus-0.2.26 → dulus-0.2.27}/memory/store.py +0 -0
  108. {dulus-0.2.26 → dulus-0.2.27}/memory/tools.py +0 -0
  109. {dulus-0.2.26 → dulus-0.2.27}/memory/types.py +0 -0
  110. {dulus-0.2.26 → dulus-0.2.27}/memory/vector_search.py +0 -0
  111. {dulus-0.2.26 → dulus-0.2.27}/multi_agent/__init__.py +0 -0
  112. {dulus-0.2.26 → dulus-0.2.27}/multi_agent/subagent.py +0 -0
  113. {dulus-0.2.26 → dulus-0.2.27}/multi_agent/tools.py +0 -0
  114. {dulus-0.2.26 → dulus-0.2.27}/offload_helper.py +0 -0
  115. {dulus-0.2.26 → dulus-0.2.27}/plugin/__init__.py +0 -0
  116. {dulus-0.2.26 → dulus-0.2.27}/plugin/autoadapter.py +0 -0
  117. {dulus-0.2.26 → dulus-0.2.27}/plugin/loader.py +0 -0
  118. {dulus-0.2.26 → dulus-0.2.27}/plugin/recommend.py +0 -0
  119. {dulus-0.2.26 → dulus-0.2.27}/plugin/store.py +0 -0
  120. {dulus-0.2.26 → dulus-0.2.27}/plugin/types.py +0 -0
  121. {dulus-0.2.26 → dulus-0.2.27}/providers.py +0 -0
  122. {dulus-0.2.26 → dulus-0.2.27}/setup.cfg +0 -0
  123. {dulus-0.2.26 → dulus-0.2.27}/skill/__init__.py +0 -0
  124. {dulus-0.2.26 → dulus-0.2.27}/skill/builtin.py +0 -0
  125. {dulus-0.2.26 → dulus-0.2.27}/skill/clawhub.py +0 -0
  126. {dulus-0.2.26 → dulus-0.2.27}/skill/executor.py +0 -0
  127. {dulus-0.2.26 → dulus-0.2.27}/skill/loader.py +0 -0
  128. {dulus-0.2.26 → dulus-0.2.27}/skill/tools.py +0 -0
  129. {dulus-0.2.26 → dulus-0.2.27}/skills.py +0 -0
  130. {dulus-0.2.26 → dulus-0.2.27}/spinner.py +0 -0
  131. {dulus-0.2.26 → dulus-0.2.27}/string_utils.py +0 -0
  132. {dulus-0.2.26 → dulus-0.2.27}/subagent.py +0 -0
  133. {dulus-0.2.26 → dulus-0.2.27}/task/__init__.py +0 -0
  134. {dulus-0.2.26 → dulus-0.2.27}/task/store.py +0 -0
  135. {dulus-0.2.26 → dulus-0.2.27}/task/tools.py +0 -0
  136. {dulus-0.2.26 → dulus-0.2.27}/task/types.py +0 -0
  137. {dulus-0.2.26 → dulus-0.2.27}/tests/test_checkpoint.py +0 -0
  138. {dulus-0.2.26 → dulus-0.2.27}/tests/test_compaction.py +0 -0
  139. {dulus-0.2.26 → dulus-0.2.27}/tests/test_diff_view.py +0 -0
  140. {dulus-0.2.26 → dulus-0.2.27}/tests/test_injection_fix.py +0 -0
  141. {dulus-0.2.26 → dulus-0.2.27}/tests/test_license.py +0 -0
  142. {dulus-0.2.26 → dulus-0.2.27}/tests/test_mcp.py +0 -0
  143. {dulus-0.2.26 → dulus-0.2.27}/tests/test_memory.py +0 -0
  144. {dulus-0.2.26 → dulus-0.2.27}/tests/test_plugin.py +0 -0
  145. {dulus-0.2.26 → dulus-0.2.27}/tests/test_skills.py +0 -0
  146. {dulus-0.2.26 → dulus-0.2.27}/tests/test_subagent.py +0 -0
  147. {dulus-0.2.26 → dulus-0.2.27}/tests/test_task.py +0 -0
  148. {dulus-0.2.26 → dulus-0.2.27}/tests/test_telegram_buffer.py +0 -0
  149. {dulus-0.2.26 → dulus-0.2.27}/tests/test_tool_registry.py +0 -0
  150. {dulus-0.2.26 → dulus-0.2.27}/tests/test_voice.py +0 -0
  151. {dulus-0.2.26 → dulus-0.2.27}/tmux_offloader.py +0 -0
  152. {dulus-0.2.26 → dulus-0.2.27}/tmux_tools.py +0 -0
  153. {dulus-0.2.26 → dulus-0.2.27}/tool_registry.py +0 -0
  154. {dulus-0.2.26 → dulus-0.2.27}/tools.py +0 -0
  155. {dulus-0.2.26 → dulus-0.2.27}/ui/__init__.py +0 -0
  156. {dulus-0.2.26 → dulus-0.2.27}/ui/input.py +0 -0
  157. {dulus-0.2.26 → dulus-0.2.27}/ui/render.py +0 -0
  158. {dulus-0.2.26 → dulus-0.2.27}/voice/__init__.py +0 -0
  159. {dulus-0.2.26 → dulus-0.2.27}/voice/keyterms.py +0 -0
  160. {dulus-0.2.26 → dulus-0.2.27}/voice/recorder.py +0 -0
  161. {dulus-0.2.26 → dulus-0.2.27}/voice/stt.py +0 -0
  162. {dulus-0.2.26 → dulus-0.2.27}/voice/tts.py +0 -0
  163. {dulus-0.2.26 → dulus-0.2.27}/webchat.py +0 -0
  164. {dulus-0.2.26 → dulus-0.2.27}/webchat_server.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dulus
3
- Version: 0.2.26
3
+ Version: 0.2.27
4
4
  Summary: Spanish-first multi-provider AI CLI — 14 NVIDIA models free, Mesa Redonda, voice, TTS, RTK token reducer, MemPalace
5
5
  Author: KevRojo
6
6
  License: GPL-3.0
@@ -69,7 +69,7 @@ SET /sticky_input ON since the first run for the best experience!
69
69
  <a href="https://pypi.org/project/dulus/"><img src="https://static.pepy.tech/badge/dulus?style=flat-square" alt="downloads"/></a>
70
70
  <img src="https://img.shields.io/badge/python-3.11+-ff6b1f?style=flat-square&labelColor=07070a" alt="python"/>
71
71
  <img src="https://img.shields.io/badge/license-GPLv3-ff6b1f?style=flat-square&labelColor=07070a" alt="license"/>
72
- <img src="https://img.shields.io/badge/version-v0.2.26-ff6b1f?style=flat-square&labelColor=07070a" alt="version"/>
72
+ <img src="https://img.shields.io/badge/version-v0.2.27-ff6b1f?style=flat-square&labelColor=07070a" alt="version"/>
73
73
  <img src="https://img.shields.io/badge/providers-11-ff6b1f?style=flat-square&labelColor=07070a" alt="providers"/>
74
74
  <img src="https://img.shields.io/badge/tools-27-ff6b1f?style=flat-square&labelColor=07070a" alt="tools"/>
75
75
  <img src="https://img.shields.io/badge/tests-263+-ff6b1f?style=flat-square&labelColor=07070a" alt="tests"/>
@@ -22,7 +22,7 @@ SET /sticky_input ON since the first run for the best experience!
22
22
  <a href="https://pypi.org/project/dulus/"><img src="https://static.pepy.tech/badge/dulus?style=flat-square" alt="downloads"/></a>
23
23
  <img src="https://img.shields.io/badge/python-3.11+-ff6b1f?style=flat-square&labelColor=07070a" alt="python"/>
24
24
  <img src="https://img.shields.io/badge/license-GPLv3-ff6b1f?style=flat-square&labelColor=07070a" alt="license"/>
25
- <img src="https://img.shields.io/badge/version-v0.2.26-ff6b1f?style=flat-square&labelColor=07070a" alt="version"/>
25
+ <img src="https://img.shields.io/badge/version-v0.2.27-ff6b1f?style=flat-square&labelColor=07070a" alt="version"/>
26
26
  <img src="https://img.shields.io/badge/providers-11-ff6b1f?style=flat-square&labelColor=07070a" alt="providers"/>
27
27
  <img src="https://img.shields.io/badge/tools-27-ff6b1f?style=flat-square&labelColor=07070a" alt="tools"/>
28
28
  <img src="https://img.shields.io/badge/tests-263+-ff6b1f?style=flat-square&labelColor=07070a" alt="tests"/>
@@ -3,6 +3,8 @@
3
3
  ## 🔥🔥🔥 News (Pacific Time)
4
4
 
5
5
 
6
+ - May 09, 2026 (**v0.2.27**): **`/bg` no longer leaves stale state** — when something else (a REPL, an old daemon) is already on `127.0.0.1:5151`, `/bg start` now refuses to spawn a duplicate that would just fail to bind, explains what's happening, and clears the stale PID file. `/bg status` self-heals: when it sees a stale PID it auto-removes it instead of complaining on every call. The previous "Some Dulus is listening on IPC, but our PID file is stale" warning is gone for good.
7
+
6
8
  - May 09, 2026 (**v0.2.26**): **`/bg start` daemon crash fix + defensive `clr()` + composio fallback**
7
9
  - **Daemon was silently crashing on launch.** `_run_daemon` printed its banner with `clr("...", "accent", "bold")`, but the default theme palette only ships {blue, cyan, gray, green, magenta, red, white, yellow} — `"accent"` raised `KeyError` and killed the process before the prompt loop started. WebChat + IPC threads, being daemon=True, died with it. Switched the banner to `"yellow"` and wrapped in try/except so a stale theme color name never takes the daemon down.
8
10
  - **`clr()` is now defensive.** Missing color keys are silently dropped instead of raising. One typo in a theme name no longer crashes the REPL.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dulus
3
- Version: 0.2.26
3
+ Version: 0.2.27
4
4
  Summary: Spanish-first multi-provider AI CLI — 14 NVIDIA models free, Mesa Redonda, voice, TTS, RTK token reducer, MemPalace
5
5
  Author: KevRojo
6
6
  License: GPL-3.0
@@ -69,7 +69,7 @@ SET /sticky_input ON since the first run for the best experience!
69
69
  <a href="https://pypi.org/project/dulus/"><img src="https://static.pepy.tech/badge/dulus?style=flat-square" alt="downloads"/></a>
70
70
  <img src="https://img.shields.io/badge/python-3.11+-ff6b1f?style=flat-square&labelColor=07070a" alt="python"/>
71
71
  <img src="https://img.shields.io/badge/license-GPLv3-ff6b1f?style=flat-square&labelColor=07070a" alt="license"/>
72
- <img src="https://img.shields.io/badge/version-v0.2.26-ff6b1f?style=flat-square&labelColor=07070a" alt="version"/>
72
+ <img src="https://img.shields.io/badge/version-v0.2.27-ff6b1f?style=flat-square&labelColor=07070a" alt="version"/>
73
73
  <img src="https://img.shields.io/badge/providers-11-ff6b1f?style=flat-square&labelColor=07070a" alt="providers"/>
74
74
  <img src="https://img.shields.io/badge/tools-27-ff6b1f?style=flat-square&labelColor=07070a" alt="tools"/>
75
75
  <img src="https://img.shields.io/badge/tests-263+-ff6b1f?style=flat-square&labelColor=07070a" alt="tests"/>
@@ -218,7 +218,7 @@ try:
218
218
  from importlib.metadata import version as _pkg_version
219
219
  VERSION = _pkg_version("dulus")
220
220
  except Exception:
221
- VERSION = "0.2.26" # dev fallback — keep in sync with pyproject.toml
221
+ VERSION = "0.2.27" # dev fallback — keep in sync with pyproject.toml
222
222
 
223
223
  # ── ANSI helpers (used even with rich for non-markdown output) ─────────────
224
224
  from common import C, clr, info, ok, warn, err, stream_thinking, print_tool_start, print_tool_end, sanitize_text
@@ -1581,9 +1581,22 @@ def cmd_bg(args: str, _state, config) -> bool:
1581
1581
  elif alive and not ipc:
1582
1582
  warn(f"PID {pid} alive but IPC port not responding (still booting?)")
1583
1583
  elif ipc:
1584
- warn("Some Dulus is listening on IPC, but our PID file is stale.")
1584
+ warn("Another Dulus (REPL or older daemon) is on the IPC port.")
1585
+ info(f" IPC: 127.0.0.1:{DULUS_IPC_PORT} (responding, but not our daemon)")
1586
+ info(" You can still reach it via `dulus \"...\"` from any shell.")
1587
+ info(" /bg start won't spawn a duplicate — kill the other one first if needed.")
1588
+ # Clear the stale PID file so this warning self-heals next time.
1589
+ try:
1590
+ BG_PID.unlink()
1591
+ except FileNotFoundError:
1592
+ pass
1585
1593
  else:
1586
1594
  info("Dulus background: NOT RUNNING")
1595
+ # Clean up any stale PID file just in case.
1596
+ try:
1597
+ BG_PID.unlink()
1598
+ except FileNotFoundError:
1599
+ pass
1587
1600
  return True
1588
1601
 
1589
1602
  # ── /bg stop ──────────────────────────────────────────────────────────
@@ -1639,6 +1652,21 @@ def cmd_bg(args: str, _state, config) -> bool:
1639
1652
  info(f"Already running (PID {existing_pid}). Use `/bg status` for details.")
1640
1653
  return True
1641
1654
 
1655
+ # Some other Dulus (a REPL on this machine, an old daemon, etc.) is
1656
+ # holding the IPC port. Spawning a new daemon would just fail to bind
1657
+ # and leave a stale PID. Better: tell the user what's up.
1658
+ if _ipc_alive():
1659
+ warn(f"Port {DULUS_IPC_PORT} is already in use by another Dulus process.")
1660
+ info("If that's a REPL you're running, this Dulus is already reachable")
1661
+ info(f" via `dulus \"...\"` from any shell — no /bg start needed.")
1662
+ info("If it's a stale daemon, find and kill it manually, then retry.")
1663
+ # Clean up the stale PID file so /bg status stops complaining.
1664
+ try:
1665
+ BG_PID.unlink()
1666
+ except FileNotFoundError:
1667
+ pass
1668
+ return True
1669
+
1642
1670
  # Parse --web-port
1643
1671
  web_port = config.get("_webchat_port", 5000)
1644
1672
  if "--web-port" in parts:
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "dulus"
7
- version = "0.2.26"
7
+ version = "0.2.27"
8
8
  description = "Spanish-first multi-provider AI CLI — 14 NVIDIA models free, Mesa Redonda, voice, TTS, RTK token reducer, MemPalace"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes