dulus 0.2.9__tar.gz → 0.2.11__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.9/dulus.egg-info → dulus-0.2.11}/PKG-INFO +22 -5
- {dulus-0.2.9 → dulus-0.2.11}/README.md +16 -3
- {dulus-0.2.9 → dulus-0.2.11/dulus.egg-info}/PKG-INFO +22 -5
- {dulus-0.2.9 → dulus-0.2.11}/dulus.egg-info/requires.txt +7 -1
- {dulus-0.2.9 → dulus-0.2.11}/pyproject.toml +12 -2
- {dulus-0.2.9 → dulus-0.2.11}/LICENSE +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/MANIFEST.in +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/agent.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/backend/__init__.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/backend/compressor.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/backend/context.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/backend/githook.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/backend/marketplace.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/backend/mempalace_bridge.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/backend/personas.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/backend/plugins.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/backend/server.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/backend/tasks.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/batch_api.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/checkpoint/__init__.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/checkpoint/hooks.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/checkpoint/store.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/checkpoint/types.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/claude_code_watcher.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/clipboard_utils.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/cloudsave.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/common.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/compaction.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/config.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/context.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/data/__init__.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/data/active_persona.json +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/data/context.json +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/data/marketplace.json +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/data/personas.json +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/data/tasks.json +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/docs/README.md +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/docs/__init__.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/docs/api.html +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/docs/architecture.md +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/docs/azure-speech-template.json +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/docs/dashboard/index.html +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/docs/divider.svg +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/docs/generate.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/docs/hero.svg +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/docs/index.html +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/docs/news.md +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/docs/nvidia-models.svg +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/docs/particle-playground.html +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/docs/personas/index.html +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/docs/preview.html +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/docs/sec-agents.svg +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/docs/sec-brainstorm.svg +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/docs/sec-bridges.svg +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/docs/sec-features.svg +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/docs/sec-freetier.svg +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/docs/sec-memory.svg +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/docs/sec-models.svg +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/docs/sec-perms.svg +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/docs/sec-plugins.svg +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/docs/sec-quickstart.svg +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/docs/sec-ssj.svg +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/docs/spinners.svg +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/docs/split-pane.svg +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/docs/terminal-boot.svg +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/docs/uploads/particle-playground.html +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/dulus.egg-info/SOURCES.txt +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/dulus.egg-info/dependency_links.txt +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/dulus.egg-info/entry_points.txt +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/dulus.egg-info/top_level.txt +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/dulus.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/dulus_gui.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/dulus_mcp/__init__.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/dulus_mcp/client.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/dulus_mcp/config.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/dulus_mcp/tools.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/dulus_mcp/types.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/gui/__init__.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/gui/agent_bridge.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/gui/chat_widget.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/gui/main_window.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/gui/personas.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/gui/session_utils.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/gui/settings_dialog.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/gui/sidebar.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/gui/tasks_view.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/gui/themes.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/gui/tool_panel.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/input.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/license_manager.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/memory/__init__.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/memory/audit.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/memory/consolidator.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/memory/context.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/memory/offload.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/memory/palace.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/memory/scan.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/memory/sessions.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/memory/store.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/memory/tools.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/memory/types.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/memory/vector_search.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/multi_agent/__init__.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/multi_agent/subagent.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/multi_agent/tools.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/offload_helper.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/plugin/__init__.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/plugin/autoadapter.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/plugin/loader.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/plugin/recommend.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/plugin/store.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/plugin/types.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/providers.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/setup.cfg +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/skill/__init__.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/skill/builtin.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/skill/clawhub.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/skill/executor.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/skill/loader.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/skill/tools.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/skills.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/spinner.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/string_utils.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/subagent.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/task/__init__.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/task/store.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/task/tools.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/task/types.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/tests/test_checkpoint.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/tests/test_compaction.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/tests/test_diff_view.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/tests/test_injection_fix.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/tests/test_license.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/tests/test_mcp.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/tests/test_memory.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/tests/test_plugin.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/tests/test_skills.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/tests/test_subagent.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/tests/test_task.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/tests/test_telegram_buffer.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/tests/test_tool_registry.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/tests/test_voice.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/tmux_offloader.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/tmux_tools.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/tool_registry.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/tools.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/ui/__init__.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/ui/input.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/ui/render.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/voice/__init__.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/voice/keyterms.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/voice/recorder.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/voice/stt.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/voice/tts.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/webchat.py +0 -0
- {dulus-0.2.9 → dulus-0.2.11}/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.11
|
|
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
|
|
@@ -29,12 +29,16 @@ Requires-Dist: httpx>=0.27.0
|
|
|
29
29
|
Requires-Dist: requests>=2.31.0
|
|
30
30
|
Requires-Dist: rich>=13.0.0
|
|
31
31
|
Requires-Dist: prompt_toolkit>=3.0.0
|
|
32
|
-
Requires-Dist: mempalace>=3.3.4
|
|
33
32
|
Requires-Dist: Flask>=3.1.3
|
|
34
33
|
Requires-Dist: bubblewrap-cli>=1.0.0
|
|
35
34
|
Requires-Dist: sounddevice
|
|
36
35
|
Requires-Dist: customtkinter>=5.2.0
|
|
37
36
|
Requires-Dist: Pillow>=10.0.0
|
|
37
|
+
Requires-Dist: typing-extensions>=4.10.0
|
|
38
|
+
Provides-Extra: memory
|
|
39
|
+
Requires-Dist: mempalace>=3.3.4; extra == "memory"
|
|
40
|
+
Provides-Extra: full
|
|
41
|
+
Requires-Dist: mempalace>=3.3.4; extra == "full"
|
|
38
42
|
Dynamic: license-file
|
|
39
43
|
|
|
40
44
|
# ▲ DULUS
|
|
@@ -84,7 +88,7 @@ SET /sticky_input ON since the first run for the best experience!
|
|
|
84
88
|
|
|
85
89
|
Dulus is a **lightweight Python reimplementation of Claude Code** that isn't locked to Claude. It ships the whole loop — REPL, tool dispatch, streaming, context compaction, checkpoints, sub-agents, voice, Telegram bridge, MCP, plugins — in roughly **12K lines you can actually read**. Fork it. Bend it. Run it offline against Qwen on your M2.
|
|
86
90
|
|
|
87
|
-
> **v0.2.
|
|
91
|
+
> **v0.2.11 — May 8, 2026** — `mempalace` moved to `[memory]` extra so `pip install dulus` is now fast and works on termux/Android out of the box (chromadb's 26 transitive deps were the resolver killer). MemPalace per-turn injection still loads at runtime when present; opt in with `pip install "dulus[memory]"`.
|
|
88
92
|
> Type `/news` to see what changed.
|
|
89
93
|
|
|
90
94
|
---
|
|
@@ -120,10 +124,11 @@ Dulus is the first one meeting multiple models at the same time working for the
|
|
|
120
124
|
### One-liner
|
|
121
125
|
|
|
122
126
|
```bash
|
|
123
|
-
pip install dulus && dulus
|
|
127
|
+
pip install dulus && dulus # core CLI — fast, no compile, works on termux
|
|
128
|
+
pip install "dulus[memory]" && dulus # +MemPalace per-turn memory (pulls chromadb)
|
|
124
129
|
```
|
|
125
130
|
|
|
126
|
-
That's it. Dulus prompts you for a key on first run.
|
|
131
|
+
That's it. Dulus prompts you for a key on first run. The `[memory]` extra pulls in `mempalace` and its `chromadb` chain — skip it on Android/termux or anywhere wheels for `numpy`/`onnxruntime` aren't available; the CLI still boots and chats fine without it.
|
|
127
132
|
|
|
128
133
|
### From source (hacking on Dulus itself)
|
|
129
134
|
|
|
@@ -133,6 +138,18 @@ pip install -e . # editable install
|
|
|
133
138
|
dulus
|
|
134
139
|
```
|
|
135
140
|
|
|
141
|
+
### Termux / Android
|
|
142
|
+
|
|
143
|
+
The default install pulls `mempalace` and `sounddevice`, both of which need a NumPy that has no prebuilt wheel for `aarch64-android` — pip will try to build NumPy from source and fail. Install around it:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
pkg install python python-numpy python-pillow build-essential
|
|
147
|
+
pip install --no-deps dulus
|
|
148
|
+
pip install anthropic openai httpx requests rich prompt_toolkit Flask bubblewrap-cli mempalace
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Skip `sounddevice` (no usable PortAudio on Android — voice features won't work anyway). Dulus's runtime is graceful: voice / MemPalace just degrade if their deps aren't there, the CLI still boots and chats fine.
|
|
152
|
+
|
|
136
153
|
### Pick a model
|
|
137
154
|
|
|
138
155
|
```bash
|
|
@@ -45,7 +45,7 @@ SET /sticky_input ON since the first run for the best experience!
|
|
|
45
45
|
|
|
46
46
|
Dulus is a **lightweight Python reimplementation of Claude Code** that isn't locked to Claude. It ships the whole loop — REPL, tool dispatch, streaming, context compaction, checkpoints, sub-agents, voice, Telegram bridge, MCP, plugins — in roughly **12K lines you can actually read**. Fork it. Bend it. Run it offline against Qwen on your M2.
|
|
47
47
|
|
|
48
|
-
> **v0.2.
|
|
48
|
+
> **v0.2.11 — May 8, 2026** — `mempalace` moved to `[memory]` extra so `pip install dulus` is now fast and works on termux/Android out of the box (chromadb's 26 transitive deps were the resolver killer). MemPalace per-turn injection still loads at runtime when present; opt in with `pip install "dulus[memory]"`.
|
|
49
49
|
> Type `/news` to see what changed.
|
|
50
50
|
|
|
51
51
|
---
|
|
@@ -81,10 +81,11 @@ Dulus is the first one meeting multiple models at the same time working for the
|
|
|
81
81
|
### One-liner
|
|
82
82
|
|
|
83
83
|
```bash
|
|
84
|
-
pip install dulus && dulus
|
|
84
|
+
pip install dulus && dulus # core CLI — fast, no compile, works on termux
|
|
85
|
+
pip install "dulus[memory]" && dulus # +MemPalace per-turn memory (pulls chromadb)
|
|
85
86
|
```
|
|
86
87
|
|
|
87
|
-
That's it. Dulus prompts you for a key on first run.
|
|
88
|
+
That's it. Dulus prompts you for a key on first run. The `[memory]` extra pulls in `mempalace` and its `chromadb` chain — skip it on Android/termux or anywhere wheels for `numpy`/`onnxruntime` aren't available; the CLI still boots and chats fine without it.
|
|
88
89
|
|
|
89
90
|
### From source (hacking on Dulus itself)
|
|
90
91
|
|
|
@@ -94,6 +95,18 @@ pip install -e . # editable install
|
|
|
94
95
|
dulus
|
|
95
96
|
```
|
|
96
97
|
|
|
98
|
+
### Termux / Android
|
|
99
|
+
|
|
100
|
+
The default install pulls `mempalace` and `sounddevice`, both of which need a NumPy that has no prebuilt wheel for `aarch64-android` — pip will try to build NumPy from source and fail. Install around it:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
pkg install python python-numpy python-pillow build-essential
|
|
104
|
+
pip install --no-deps dulus
|
|
105
|
+
pip install anthropic openai httpx requests rich prompt_toolkit Flask bubblewrap-cli mempalace
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Skip `sounddevice` (no usable PortAudio on Android — voice features won't work anyway). Dulus's runtime is graceful: voice / MemPalace just degrade if their deps aren't there, the CLI still boots and chats fine.
|
|
109
|
+
|
|
97
110
|
### Pick a model
|
|
98
111
|
|
|
99
112
|
```bash
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dulus
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.11
|
|
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
|
|
@@ -29,12 +29,16 @@ Requires-Dist: httpx>=0.27.0
|
|
|
29
29
|
Requires-Dist: requests>=2.31.0
|
|
30
30
|
Requires-Dist: rich>=13.0.0
|
|
31
31
|
Requires-Dist: prompt_toolkit>=3.0.0
|
|
32
|
-
Requires-Dist: mempalace>=3.3.4
|
|
33
32
|
Requires-Dist: Flask>=3.1.3
|
|
34
33
|
Requires-Dist: bubblewrap-cli>=1.0.0
|
|
35
34
|
Requires-Dist: sounddevice
|
|
36
35
|
Requires-Dist: customtkinter>=5.2.0
|
|
37
36
|
Requires-Dist: Pillow>=10.0.0
|
|
37
|
+
Requires-Dist: typing-extensions>=4.10.0
|
|
38
|
+
Provides-Extra: memory
|
|
39
|
+
Requires-Dist: mempalace>=3.3.4; extra == "memory"
|
|
40
|
+
Provides-Extra: full
|
|
41
|
+
Requires-Dist: mempalace>=3.3.4; extra == "full"
|
|
38
42
|
Dynamic: license-file
|
|
39
43
|
|
|
40
44
|
# ▲ DULUS
|
|
@@ -84,7 +88,7 @@ SET /sticky_input ON since the first run for the best experience!
|
|
|
84
88
|
|
|
85
89
|
Dulus is a **lightweight Python reimplementation of Claude Code** that isn't locked to Claude. It ships the whole loop — REPL, tool dispatch, streaming, context compaction, checkpoints, sub-agents, voice, Telegram bridge, MCP, plugins — in roughly **12K lines you can actually read**. Fork it. Bend it. Run it offline against Qwen on your M2.
|
|
86
90
|
|
|
87
|
-
> **v0.2.
|
|
91
|
+
> **v0.2.11 — May 8, 2026** — `mempalace` moved to `[memory]` extra so `pip install dulus` is now fast and works on termux/Android out of the box (chromadb's 26 transitive deps were the resolver killer). MemPalace per-turn injection still loads at runtime when present; opt in with `pip install "dulus[memory]"`.
|
|
88
92
|
> Type `/news` to see what changed.
|
|
89
93
|
|
|
90
94
|
---
|
|
@@ -120,10 +124,11 @@ Dulus is the first one meeting multiple models at the same time working for the
|
|
|
120
124
|
### One-liner
|
|
121
125
|
|
|
122
126
|
```bash
|
|
123
|
-
pip install dulus && dulus
|
|
127
|
+
pip install dulus && dulus # core CLI — fast, no compile, works on termux
|
|
128
|
+
pip install "dulus[memory]" && dulus # +MemPalace per-turn memory (pulls chromadb)
|
|
124
129
|
```
|
|
125
130
|
|
|
126
|
-
That's it. Dulus prompts you for a key on first run.
|
|
131
|
+
That's it. Dulus prompts you for a key on first run. The `[memory]` extra pulls in `mempalace` and its `chromadb` chain — skip it on Android/termux or anywhere wheels for `numpy`/`onnxruntime` aren't available; the CLI still boots and chats fine without it.
|
|
127
132
|
|
|
128
133
|
### From source (hacking on Dulus itself)
|
|
129
134
|
|
|
@@ -133,6 +138,18 @@ pip install -e . # editable install
|
|
|
133
138
|
dulus
|
|
134
139
|
```
|
|
135
140
|
|
|
141
|
+
### Termux / Android
|
|
142
|
+
|
|
143
|
+
The default install pulls `mempalace` and `sounddevice`, both of which need a NumPy that has no prebuilt wheel for `aarch64-android` — pip will try to build NumPy from source and fail. Install around it:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
pkg install python python-numpy python-pillow build-essential
|
|
147
|
+
pip install --no-deps dulus
|
|
148
|
+
pip install anthropic openai httpx requests rich prompt_toolkit Flask bubblewrap-cli mempalace
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Skip `sounddevice` (no usable PortAudio on Android — voice features won't work anyway). Dulus's runtime is graceful: voice / MemPalace just degrade if their deps aren't there, the CLI still boots and chats fine.
|
|
152
|
+
|
|
136
153
|
### Pick a model
|
|
137
154
|
|
|
138
155
|
```bash
|
|
@@ -4,9 +4,15 @@ httpx>=0.27.0
|
|
|
4
4
|
requests>=2.31.0
|
|
5
5
|
rich>=13.0.0
|
|
6
6
|
prompt_toolkit>=3.0.0
|
|
7
|
-
mempalace>=3.3.4
|
|
8
7
|
Flask>=3.1.3
|
|
9
8
|
bubblewrap-cli>=1.0.0
|
|
10
9
|
sounddevice
|
|
11
10
|
customtkinter>=5.2.0
|
|
12
11
|
Pillow>=10.0.0
|
|
12
|
+
typing-extensions>=4.10.0
|
|
13
|
+
|
|
14
|
+
[full]
|
|
15
|
+
mempalace>=3.3.4
|
|
16
|
+
|
|
17
|
+
[memory]
|
|
18
|
+
mempalace>=3.3.4
|
|
@@ -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.11"
|
|
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"
|
|
@@ -34,14 +34,24 @@ dependencies = [
|
|
|
34
34
|
"requests>=2.31.0",
|
|
35
35
|
"rich>=13.0.0",
|
|
36
36
|
"prompt_toolkit>=3.0.0",
|
|
37
|
-
"mempalace>=3.3.4",
|
|
38
37
|
"Flask>=3.1.3",
|
|
39
38
|
"bubblewrap-cli>=1.0.0",
|
|
40
39
|
"sounddevice",
|
|
41
40
|
"customtkinter>=5.2.0",
|
|
42
41
|
"Pillow>=10.0.0",
|
|
42
|
+
"typing-extensions>=4.10.0",
|
|
43
43
|
]
|
|
44
44
|
|
|
45
|
+
# mempalace pulls chromadb (26 transitive deps incl. numpy + onnxruntime),
|
|
46
|
+
# which on termux/aarch64 has no wheels and on regular installs sends pip's
|
|
47
|
+
# resolver into a backtracking loop trying to reconcile typing-extensions /
|
|
48
|
+
# pydantic / httpx ranges. Keeping it optional lets `pip install dulus` succeed
|
|
49
|
+
# in seconds everywhere; power users opt in with `pip install dulus[memory]`
|
|
50
|
+
# (or `dulus[full]`) when they want MemPalace per-turn injection.
|
|
51
|
+
[project.optional-dependencies]
|
|
52
|
+
memory = ["mempalace>=3.3.4"]
|
|
53
|
+
full = ["mempalace>=3.3.4"]
|
|
54
|
+
|
|
45
55
|
[project.scripts]
|
|
46
56
|
dulus = "dulus:main"
|
|
47
57
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|