dulus 0.2.19__tar.gz → 0.2.21__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.19/dulus.egg-info → dulus-0.2.21}/PKG-INFO +2 -2
- {dulus-0.2.19 → dulus-0.2.21}/README.md +1 -1
- {dulus-0.2.19 → dulus-0.2.21}/context.py +1 -0
- {dulus-0.2.19 → dulus-0.2.21}/docs/news.md +4 -0
- {dulus-0.2.19 → dulus-0.2.21/dulus.egg-info}/PKG-INFO +2 -2
- {dulus-0.2.19 → dulus-0.2.21}/dulus.py +10 -2
- {dulus-0.2.19 → dulus-0.2.21}/pyproject.toml +1 -1
- {dulus-0.2.19 → dulus-0.2.21}/LICENSE +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/MANIFEST.in +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/agent.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/backend/__init__.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/backend/compressor.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/backend/context.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/backend/githook.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/backend/marketplace.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/backend/mempalace_bridge.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/backend/personas.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/backend/plugins.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/backend/server.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/backend/tasks.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/batch_api.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/checkpoint/__init__.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/checkpoint/hooks.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/checkpoint/store.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/checkpoint/types.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/claude_code_watcher.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/clipboard_utils.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/cloudsave.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/common.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/compaction.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/config.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/data/__init__.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/data/active_persona.json +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/data/context.json +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/data/marketplace.json +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/data/personas.json +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/data/plugins/__init__.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/data/plugins/composio/__init__.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/data/plugins/composio/composio_plugin/__init__.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/data/plugins/composio/composio_plugin/session_manager.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/data/plugins/composio/composio_plugin/tool_generator.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/data/plugins/composio/plugin.json +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/data/plugins/composio/plugin_tool.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/data/tasks.json +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/docs/README.md +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/docs/__init__.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/docs/api.html +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/docs/architecture.md +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/docs/azure-speech-template.json +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/docs/dashboard/index.html +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/docs/divider.svg +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/docs/generate.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/docs/hero.svg +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/docs/index.html +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/docs/nvidia-models.svg +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/docs/particle-playground.html +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/docs/personas/index.html +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/docs/poetry-banner.png +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/docs/preview.html +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/docs/sec-agents.svg +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/docs/sec-brainstorm.svg +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/docs/sec-bridges.svg +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/docs/sec-features.svg +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/docs/sec-freetier.svg +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/docs/sec-memory.svg +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/docs/sec-models.svg +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/docs/sec-perms.svg +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/docs/sec-plugins.svg +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/docs/sec-quickstart.svg +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/docs/sec-ssj.svg +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/docs/spinners.svg +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/docs/split-pane.svg +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/docs/terminal-boot.svg +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/docs/uploads/particle-playground.html +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/dulus.egg-info/SOURCES.txt +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/dulus.egg-info/dependency_links.txt +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/dulus.egg-info/entry_points.txt +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/dulus.egg-info/requires.txt +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/dulus.egg-info/top_level.txt +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/dulus_gui.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/dulus_mcp/__init__.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/dulus_mcp/client.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/dulus_mcp/config.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/dulus_mcp/tools.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/dulus_mcp/types.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/gui/__init__.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/gui/agent_bridge.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/gui/chat_widget.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/gui/main_window.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/gui/personas.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/gui/session_utils.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/gui/settings_dialog.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/gui/sidebar.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/gui/tasks_view.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/gui/themes.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/gui/tool_panel.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/input.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/license_manager.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/memory/__init__.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/memory/audit.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/memory/consolidator.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/memory/context.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/memory/offload.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/memory/palace.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/memory/scan.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/memory/sessions.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/memory/store.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/memory/tools.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/memory/types.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/memory/vector_search.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/multi_agent/__init__.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/multi_agent/subagent.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/multi_agent/tools.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/offload_helper.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/plugin/__init__.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/plugin/autoadapter.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/plugin/loader.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/plugin/recommend.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/plugin/store.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/plugin/types.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/providers.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/setup.cfg +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/skill/__init__.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/skill/builtin.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/skill/clawhub.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/skill/executor.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/skill/loader.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/skill/tools.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/skills.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/spinner.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/string_utils.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/subagent.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/task/__init__.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/task/store.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/task/tools.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/task/types.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/tests/test_checkpoint.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/tests/test_compaction.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/tests/test_diff_view.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/tests/test_injection_fix.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/tests/test_license.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/tests/test_mcp.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/tests/test_memory.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/tests/test_plugin.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/tests/test_skills.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/tests/test_subagent.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/tests/test_task.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/tests/test_telegram_buffer.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/tests/test_tool_registry.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/tests/test_voice.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/tmux_offloader.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/tmux_tools.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/tool_registry.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/tools.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/ui/__init__.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/ui/input.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/ui/render.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/voice/__init__.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/voice/keyterms.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/voice/recorder.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/voice/stt.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/voice/tts.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/webchat.py +0 -0
- {dulus-0.2.19 → dulus-0.2.21}/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.21
|
|
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.21-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.21-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"/>
|
|
@@ -19,6 +19,7 @@ You are Dulus, an AI coding agent. Think in English; reply to KevRojo in Dominic
|
|
|
19
19
|
# Env: {cwd} | {platform} | auto_show={auto_show}
|
|
20
20
|
# Autonomy: Background scripts (nohup/&) allowed | Never refuse monitoring/long tasks | Always wait for tool results before replying
|
|
21
21
|
# Tools: SearchLastOutput → for [TRUNCATED] | WebFetch/WebSearch → web | TmuxOffload → tasks > 5s | ReadJob → background results
|
|
22
|
+
# SleepTimer: ONLY for user-facing reminders/notifications (e.g. "remind me in 10min"). NEVER use it to wait between your own tool calls — it freezes the console. To pause inside a command sequence, put `sleep N` INSIDE the Bash command itself (e.g. Bash('cmd1 && sleep 2 && cmd2')).
|
|
22
23
|
# Multi-agent: Agent(subagent_type=...) | isolation="worktree" runs parallel | wait=false + name=... for fire-and-forget
|
|
23
24
|
# Rules: Edit > Write | Use absolute paths + line numbers | Surface errors immediately, do not retry blindly
|
|
24
25
|
# Input: "🎙 Transcribed:" prefix = voice input — tolerate typos/misspellings
|
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
## 🔥🔥🔥 News (Pacific Time)
|
|
4
4
|
|
|
5
5
|
|
|
6
|
+
- May 09, 2026 (**v0.2.21**): **System prompt clarifies SleepTimer scope** — added an explicit hint that SleepTimer is ONLY for user-facing reminders/notifications, NEVER for inter-tool waits (those freeze the console). When a pause is needed mid-pipeline, models should use `sleep N` inside the Bash command itself. Fixes a recurring console-freeze when models reflexively reached for SleepTimer between commands.
|
|
7
|
+
|
|
8
|
+
- May 09, 2026 (**v0.2.20**): **IPC port-collision fix on Windows** — `SO_REUSEADDR` on Windows lets two sockets share the same port, which would let a second Dulus instance silently "steal" the IPC listener. Switched to `SO_EXCLUSIVEADDRUSE` so the second instance correctly backs off and acts as a client. Verified end-to-end with the new test harness.
|
|
9
|
+
|
|
6
10
|
- May 09, 2026 (**v0.2.19**): **Shared sessions via tiny TCP socket — daemon workaround supremo**
|
|
7
11
|
- **One Dulus, many shells.** When a Dulus REPL or `--daemon` is running, it now listens on `127.0.0.1:5151`. Any subsequent `dulus "do X"` from another shell forwards the prompt to that live session over the socket and prints back the reply — same history, same memory, same plugins, same tool state. No session manager, no IPC framework, no systemd unit. 80 lines of plain TCP.
|
|
8
12
|
- **Falls back gracefully.** If no listener is up, the CLI behaves exactly as before (spawns its own `--print` process). Daemon/gui/`--cmd`/`--run-tool` modes intentionally bypass the IPC dispatch — they need their own process.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dulus
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.21
|
|
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.21-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.
|
|
221
|
+
VERSION = "0.2.21" # 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
|
|
@@ -3739,7 +3739,15 @@ def _ipc_server_loop(config, state):
|
|
|
3739
3739
|
import json as _json
|
|
3740
3740
|
|
|
3741
3741
|
sock = _socket.socket(_socket.AF_INET, _socket.SOCK_STREAM)
|
|
3742
|
-
|
|
3742
|
+
# On Windows, SO_REUSEADDR lets two sockets share a port — wrong here; we
|
|
3743
|
+
# want a hard "port is taken, back off." SO_EXCLUSIVEADDRUSE gives us that.
|
|
3744
|
+
# On Linux, SO_REUSEADDR only matters for TIME_WAIT recovery, so skipping
|
|
3745
|
+
# it is fine — restart cooldown is a few seconds at worst.
|
|
3746
|
+
if hasattr(_socket, "SO_EXCLUSIVEADDRUSE"):
|
|
3747
|
+
try:
|
|
3748
|
+
sock.setsockopt(_socket.SOL_SOCKET, _socket.SO_EXCLUSIVEADDRUSE, 1)
|
|
3749
|
+
except OSError:
|
|
3750
|
+
pass
|
|
3743
3751
|
try:
|
|
3744
3752
|
sock.bind((DULUS_IPC_HOST, DULUS_IPC_PORT))
|
|
3745
3753
|
except OSError:
|
|
@@ -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.21"
|
|
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
|