dulus 0.2.29__tar.gz → 0.2.30__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.
- {dulus-0.2.29/dulus.egg-info → dulus-0.2.30}/PKG-INFO +2 -2
- {dulus-0.2.29 → dulus-0.2.30}/README.md +1 -1
- {dulus-0.2.29 → dulus-0.2.30}/docs/news.md +2 -0
- {dulus-0.2.29 → dulus-0.2.30/dulus.egg-info}/PKG-INFO +2 -2
- {dulus-0.2.29 → dulus-0.2.30}/dulus.py +54 -17
- {dulus-0.2.29 → dulus-0.2.30}/pyproject.toml +1 -1
- {dulus-0.2.29 → dulus-0.2.30}/LICENSE +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/MANIFEST.in +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/agent.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/backend/__init__.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/backend/compressor.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/backend/context.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/backend/githook.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/backend/marketplace.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/backend/mempalace_bridge.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/backend/personas.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/backend/plugins.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/backend/server.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/backend/tasks.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/batch_api.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/checkpoint/__init__.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/checkpoint/hooks.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/checkpoint/store.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/checkpoint/types.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/claude_code_watcher.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/clipboard_utils.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/cloudsave.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/common.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/compaction.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/config.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/context.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/data/__init__.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/data/active_persona.json +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/data/context.json +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/data/marketplace.json +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/data/personas.json +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/data/plugins/__init__.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/data/plugins/composio/__init__.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/data/plugins/composio/composio_plugin/__init__.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/data/plugins/composio/composio_plugin/session_manager.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/data/plugins/composio/composio_plugin/tool_generator.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/data/plugins/composio/plugin.json +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/data/plugins/composio/plugin_tool.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/data/tasks.json +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/docs/README.md +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/docs/__init__.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/docs/api.html +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/docs/architecture.md +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/docs/azure-speech-template.json +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/docs/dashboard/index.html +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/docs/divider.svg +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/docs/generate.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/docs/hero.svg +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/docs/index.html +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/docs/nvidia-models.svg +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/docs/particle-playground.html +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/docs/personas/index.html +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/docs/poetry-banner.png +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/docs/preview.html +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/docs/sec-agents.svg +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/docs/sec-brainstorm.svg +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/docs/sec-bridges.svg +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/docs/sec-features.svg +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/docs/sec-freetier.svg +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/docs/sec-memory.svg +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/docs/sec-models.svg +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/docs/sec-perms.svg +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/docs/sec-plugins.svg +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/docs/sec-quickstart.svg +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/docs/sec-ssj.svg +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/docs/spinners.svg +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/docs/split-pane.svg +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/docs/terminal-boot.svg +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/docs/uploads/particle-playground.html +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/dulus.egg-info/SOURCES.txt +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/dulus.egg-info/dependency_links.txt +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/dulus.egg-info/entry_points.txt +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/dulus.egg-info/requires.txt +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/dulus.egg-info/top_level.txt +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/dulus_gui.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/dulus_mcp/__init__.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/dulus_mcp/client.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/dulus_mcp/config.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/dulus_mcp/tools.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/dulus_mcp/types.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/gui/__init__.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/gui/agent_bridge.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/gui/chat_widget.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/gui/main_window.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/gui/personas.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/gui/session_utils.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/gui/settings_dialog.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/gui/sidebar.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/gui/tasks_view.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/gui/themes.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/gui/tool_panel.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/input.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/license_manager.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/memory/__init__.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/memory/audit.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/memory/consolidator.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/memory/context.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/memory/offload.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/memory/palace.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/memory/scan.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/memory/sessions.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/memory/store.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/memory/tools.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/memory/types.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/memory/vector_search.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/multi_agent/__init__.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/multi_agent/subagent.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/multi_agent/tools.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/offload_helper.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/plugin/__init__.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/plugin/autoadapter.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/plugin/loader.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/plugin/recommend.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/plugin/store.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/plugin/types.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/providers.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/setup.cfg +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/skill/__init__.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/skill/builtin.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/skill/clawhub.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/skill/executor.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/skill/loader.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/skill/tools.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/skills.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/spinner.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/string_utils.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/subagent.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/task/__init__.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/task/store.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/task/tools.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/task/types.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/tests/test_checkpoint.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/tests/test_compaction.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/tests/test_diff_view.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/tests/test_injection_fix.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/tests/test_license.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/tests/test_mcp.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/tests/test_memory.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/tests/test_plugin.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/tests/test_skills.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/tests/test_subagent.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/tests/test_task.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/tests/test_telegram_buffer.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/tests/test_tool_registry.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/tests/test_voice.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/tmux_offloader.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/tmux_tools.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/tool_registry.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/tools.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/ui/__init__.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/ui/input.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/ui/render.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/voice/__init__.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/voice/keyterms.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/voice/recorder.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/voice/stt.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/voice/tts.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/webchat.py +0 -0
- {dulus-0.2.29 → dulus-0.2.30}/webchat_server.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dulus
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.30
|
|
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.
|
|
72
|
+
<img src="https://img.shields.io/badge/version-v0.2.30-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.
|
|
25
|
+
<img src="https://img.shields.io/badge/version-v0.2.30-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.30**): **`/bg start` daemon is now truly windowless on Windows** — `python.exe` is a console-subsystem binary, so even with `DETACHED_PROCESS` Windows still spun up a visible console window for the daemon. Closing that window killed the daemon. Switched to `pythonw.exe` (the GUI-subsystem variant) + `CREATE_NO_WINDOW` so the daemon spawns with NO console window at all. Verified: `Get-Process` reports `MainWindowHandle = 0` after spawn — there's literally nothing to close. Telegram + WebChat + IPC keep running in background until `/bg stop` or `/bg kill`.
|
|
7
|
+
|
|
6
8
|
- May 09, 2026 (**v0.2.29**): **`/bg start` actually works from inside a REPL + daemon-mode webchat default-on + tested end-to-end this time**
|
|
7
9
|
- **The whole point of `/bg start` was broken from day one.** A REPL itself binds `127.0.0.1:5151` to serve `dulus "..."` shell calls, so the moment you typed `/bg start` from inside that REPL, the duplicate-detection check saw "port in use" and refused — by the very REPL invoking the command. `/bg kill` then killed the only thing on the port: your own REPL. Pure logic flaw on me.
|
|
8
10
|
- **Now `/bg start` releases the REPL's own IPC first.** When invoked from inside a REPL, the command stops the REPL's IPC thread, force-closes the socket with `SO_LINGER {1, 0}` (skips TIME_WAIT), waits ~600ms for the OS to free the port, and only then spawns the daemon. The REPL keeps running — it just becomes a normal client whose `dulus "..."` dispatches now go to the daemon.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dulus
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.30
|
|
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.
|
|
72
|
+
<img src="https://img.shields.io/badge/version-v0.2.30-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"/>
|
|
@@ -122,6 +122,26 @@ if sys.platform == "win32":
|
|
|
122
122
|
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
|
|
123
123
|
if hasattr(sys.stderr, "reconfigure"):
|
|
124
124
|
sys.stderr.reconfigure(encoding="utf-8", errors="replace")
|
|
125
|
+
|
|
126
|
+
# ── Suppress noisy third-party startup warnings ──────────────────────────
|
|
127
|
+
# These don't affect functionality but pollute every Dulus boot (REPL,
|
|
128
|
+
# daemon, --print, every shell call). Filtered globally so logs stay clean.
|
|
129
|
+
import warnings as _warnings
|
|
130
|
+
# requests >= 2.32 nags about urllib3/chardet version pins on Python 3.13+.
|
|
131
|
+
_warnings.filterwarnings("ignore", message=r".*urllib3.*")
|
|
132
|
+
_warnings.filterwarnings("ignore", message=r".*chardet.*charset_normalizer.*")
|
|
133
|
+
_warnings.filterwarnings("ignore", message=r".*RequestsDependencyWarning.*")
|
|
134
|
+
# Dulus's own dev-license warning — only relevant if you're building
|
|
135
|
+
# license keys for production, not noise we want on every boot.
|
|
136
|
+
_warnings.filterwarnings("ignore", message=r".*DULUS_LICENSE_SECRET.*")
|
|
137
|
+
# Catch-all: any RequestsDependencyWarning by category, regardless of msg.
|
|
138
|
+
try:
|
|
139
|
+
from requests.exceptions import RequestsDependencyWarning as _RDW # type: ignore
|
|
140
|
+
_warnings.filterwarnings("ignore", category=_RDW)
|
|
141
|
+
except Exception:
|
|
142
|
+
pass
|
|
143
|
+
# pkg_resources / setuptools-based deprecations from optional plugins.
|
|
144
|
+
_warnings.filterwarnings("ignore", category=DeprecationWarning, module=r"pkg_resources.*")
|
|
125
145
|
from pathlib import Path
|
|
126
146
|
|
|
127
147
|
# ── Global Import Hook ───────────────────────────────────────────────────────
|
|
@@ -218,7 +238,7 @@ try:
|
|
|
218
238
|
from importlib.metadata import version as _pkg_version
|
|
219
239
|
VERSION = _pkg_version("dulus")
|
|
220
240
|
except Exception:
|
|
221
|
-
VERSION = "0.2.
|
|
241
|
+
VERSION = "0.2.30" # dev fallback — keep in sync with pyproject.toml
|
|
222
242
|
|
|
223
243
|
# ── ANSI helpers (used even with rich for non-markdown output) ─────────────
|
|
224
244
|
from common import C, clr, info, ok, warn, err, stream_thinking, print_tool_start, print_tool_end, sanitize_text
|
|
@@ -1766,20 +1786,32 @@ def cmd_bg(args: str, _state, config) -> bool:
|
|
|
1766
1786
|
from config import save_config
|
|
1767
1787
|
save_config(config)
|
|
1768
1788
|
|
|
1769
|
-
# Build the spawn command.
|
|
1770
|
-
#
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
else:
|
|
1789
|
+
# Build the spawn command. On Windows we MUST use pythonw.exe (windowless
|
|
1790
|
+
# variant) instead of the console-subsystem python.exe / dulus shim,
|
|
1791
|
+
# otherwise Windows creates a visible console window for the daemon
|
|
1792
|
+
# and closing it kills the process. The shim itself runs python.exe,
|
|
1793
|
+
# so we go around it by invoking pythonw -m dulus directly.
|
|
1794
|
+
if _sys.platform == "win32":
|
|
1795
|
+
pythonw = _sys.executable.replace("python.exe", "pythonw.exe")
|
|
1796
|
+
if not _os.path.exists(pythonw):
|
|
1797
|
+
# Fall back to python.exe if pythonw isn't shipped (rare;
|
|
1798
|
+
# mostly happens on stripped embeddable distributions).
|
|
1799
|
+
pythonw = _sys.executable
|
|
1781
1800
|
dulus_script = _os.path.abspath(__file__)
|
|
1782
|
-
cmd = [
|
|
1801
|
+
cmd = [pythonw, dulus_script, "--daemon"]
|
|
1802
|
+
else:
|
|
1803
|
+
from shutil import which
|
|
1804
|
+
dulus_bin = None
|
|
1805
|
+
for cand in ["dulus", "dulus.exe"]:
|
|
1806
|
+
p = which(cand)
|
|
1807
|
+
if p:
|
|
1808
|
+
dulus_bin = p
|
|
1809
|
+
break
|
|
1810
|
+
if dulus_bin:
|
|
1811
|
+
cmd = [dulus_bin, "--daemon"]
|
|
1812
|
+
else:
|
|
1813
|
+
dulus_script = _os.path.abspath(__file__)
|
|
1814
|
+
cmd = [_sys.executable, dulus_script, "--daemon"]
|
|
1783
1815
|
|
|
1784
1816
|
# Pass the auto-webchat hint via env so the daemon picks it up.
|
|
1785
1817
|
env = _os.environ.copy()
|
|
@@ -1790,13 +1822,18 @@ def cmd_bg(args: str, _state, config) -> bool:
|
|
|
1790
1822
|
log_fp = open(BG_LOG, "ab")
|
|
1791
1823
|
try:
|
|
1792
1824
|
if _sys.platform == "win32":
|
|
1793
|
-
#
|
|
1794
|
-
|
|
1825
|
+
# CREATE_NO_WINDOW (0x08000000) suppresses the console window
|
|
1826
|
+
# entirely — cannot be combined with DETACHED_PROCESS, but
|
|
1827
|
+
# because we're invoking pythonw.exe (a GUI-subsystem binary)
|
|
1828
|
+
# there is no console to inherit from in the first place.
|
|
1829
|
+
# CREATE_NEW_PROCESS_GROUP keeps Ctrl+C in the parent shell
|
|
1830
|
+
# from killing the daemon when the parent later exits.
|
|
1831
|
+
CREATE_NO_WINDOW = 0x08000000
|
|
1795
1832
|
NEW_GROUP = 0x00000200
|
|
1796
1833
|
proc = _sp.Popen(
|
|
1797
1834
|
cmd,
|
|
1798
1835
|
stdout=log_fp, stderr=log_fp, stdin=_sp.DEVNULL,
|
|
1799
|
-
creationflags=
|
|
1836
|
+
creationflags=CREATE_NO_WINDOW | NEW_GROUP,
|
|
1800
1837
|
close_fds=True,
|
|
1801
1838
|
env=env,
|
|
1802
1839
|
)
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "dulus"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.30"
|
|
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
|
|
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
|