dulus 0.2.15__tar.gz → 0.2.16__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.15/dulus.egg-info → dulus-0.2.16}/PKG-INFO +6 -2
- {dulus-0.2.15 → dulus-0.2.16}/README.md +5 -1
- {dulus-0.2.15 → dulus-0.2.16}/docs/news.md +8 -0
- {dulus-0.2.15 → dulus-0.2.16/dulus.egg-info}/PKG-INFO +6 -2
- {dulus-0.2.15 → dulus-0.2.16}/dulus.py +39 -0
- {dulus-0.2.15 → dulus-0.2.16}/pyproject.toml +1 -1
- {dulus-0.2.15 → dulus-0.2.16}/LICENSE +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/MANIFEST.in +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/agent.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/backend/__init__.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/backend/compressor.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/backend/context.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/backend/githook.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/backend/marketplace.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/backend/mempalace_bridge.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/backend/personas.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/backend/plugins.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/backend/server.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/backend/tasks.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/batch_api.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/checkpoint/__init__.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/checkpoint/hooks.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/checkpoint/store.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/checkpoint/types.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/claude_code_watcher.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/clipboard_utils.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/cloudsave.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/common.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/compaction.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/config.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/context.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/data/__init__.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/data/active_persona.json +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/data/context.json +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/data/marketplace.json +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/data/personas.json +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/data/tasks.json +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/docs/README.md +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/docs/__init__.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/docs/api.html +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/docs/architecture.md +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/docs/azure-speech-template.json +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/docs/dashboard/index.html +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/docs/divider.svg +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/docs/generate.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/docs/hero.svg +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/docs/index.html +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/docs/nvidia-models.svg +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/docs/particle-playground.html +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/docs/personas/index.html +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/docs/poetry-banner.png +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/docs/preview.html +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/docs/sec-agents.svg +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/docs/sec-brainstorm.svg +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/docs/sec-bridges.svg +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/docs/sec-features.svg +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/docs/sec-freetier.svg +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/docs/sec-memory.svg +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/docs/sec-models.svg +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/docs/sec-perms.svg +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/docs/sec-plugins.svg +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/docs/sec-quickstart.svg +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/docs/sec-ssj.svg +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/docs/spinners.svg +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/docs/split-pane.svg +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/docs/terminal-boot.svg +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/docs/uploads/particle-playground.html +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/dulus.egg-info/SOURCES.txt +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/dulus.egg-info/dependency_links.txt +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/dulus.egg-info/entry_points.txt +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/dulus.egg-info/requires.txt +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/dulus.egg-info/top_level.txt +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/dulus_gui.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/dulus_mcp/__init__.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/dulus_mcp/client.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/dulus_mcp/config.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/dulus_mcp/tools.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/dulus_mcp/types.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/gui/__init__.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/gui/agent_bridge.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/gui/chat_widget.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/gui/main_window.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/gui/personas.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/gui/session_utils.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/gui/settings_dialog.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/gui/sidebar.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/gui/tasks_view.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/gui/themes.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/gui/tool_panel.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/input.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/license_manager.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/memory/__init__.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/memory/audit.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/memory/consolidator.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/memory/context.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/memory/offload.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/memory/palace.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/memory/scan.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/memory/sessions.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/memory/store.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/memory/tools.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/memory/types.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/memory/vector_search.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/multi_agent/__init__.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/multi_agent/subagent.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/multi_agent/tools.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/offload_helper.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/plugin/__init__.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/plugin/autoadapter.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/plugin/loader.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/plugin/recommend.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/plugin/store.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/plugin/types.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/providers.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/setup.cfg +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/skill/__init__.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/skill/builtin.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/skill/clawhub.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/skill/executor.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/skill/loader.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/skill/tools.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/skills.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/spinner.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/string_utils.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/subagent.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/task/__init__.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/task/store.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/task/tools.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/task/types.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/tests/test_checkpoint.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/tests/test_compaction.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/tests/test_diff_view.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/tests/test_injection_fix.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/tests/test_license.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/tests/test_mcp.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/tests/test_memory.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/tests/test_plugin.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/tests/test_skills.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/tests/test_subagent.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/tests/test_task.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/tests/test_telegram_buffer.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/tests/test_tool_registry.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/tests/test_voice.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/tmux_offloader.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/tmux_tools.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/tool_registry.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/tools.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/ui/__init__.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/ui/input.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/ui/render.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/voice/__init__.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/voice/keyterms.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/voice/recorder.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/voice/stt.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/voice/tts.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/webchat.py +0 -0
- {dulus-0.2.15 → dulus-0.2.16}/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.16
|
|
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
|
|
@@ -67,7 +67,7 @@ SET /sticky_input ON since the first run for the best experience!
|
|
|
67
67
|
<a href="https://pypi.org/project/dulus/"><img src="https://static.pepy.tech/badge/dulus?style=flat-square" alt="downloads"/></a>
|
|
68
68
|
<img src="https://img.shields.io/badge/python-3.11+-ff6b1f?style=flat-square&labelColor=07070a" alt="python"/>
|
|
69
69
|
<img src="https://img.shields.io/badge/license-GPLv3-ff6b1f?style=flat-square&labelColor=07070a" alt="license"/>
|
|
70
|
-
<img src="https://img.shields.io/badge/version-v0.2.
|
|
70
|
+
<img src="https://img.shields.io/badge/version-v0.2.16-ff6b1f?style=flat-square&labelColor=07070a" alt="version"/>
|
|
71
71
|
<img src="https://img.shields.io/badge/providers-11-ff6b1f?style=flat-square&labelColor=07070a" alt="providers"/>
|
|
72
72
|
<img src="https://img.shields.io/badge/tools-27-ff6b1f?style=flat-square&labelColor=07070a" alt="tools"/>
|
|
73
73
|
<img src="https://img.shields.io/badge/tests-263+-ff6b1f?style=flat-square&labelColor=07070a" alt="tests"/>
|
|
@@ -90,6 +90,7 @@ SET /sticky_input ON since the first run for the best experience!
|
|
|
90
90
|
Talent cant be copied.
|
|
91
91
|
|
|
92
92
|
Dulus Reduce your IA costs by 60% parsing webchats and claude-code directly. Write poetry while Anthropic only see text.
|
|
93
|
+
Use claude-code as an API without the new 'extra-usage' wall <3
|
|
93
94
|
|
|
94
95
|
<p align="center"><img src="https://raw.githubusercontent.com/KevRojo/Dulus/main/docs/poetry-banner.png" alt="Anthropic only sees text while you and Claude are writing poetry" width="100%"></p>
|
|
95
96
|
|
|
@@ -622,6 +623,9 @@ git diff | dulus -p "write a commit message"
|
|
|
622
623
|
GPLv3. Fork it, modify it, redistribute it — but keep it open. Derivative works must stay under GPLv3. Just don't ship `--accept-all` as the default.
|
|
623
624
|
|
|
624
625
|
---
|
|
626
|
+
Donations:
|
|
627
|
+
|
|
628
|
+
Bitcoin: 1JzatQDn9fMLnKTd3KYgztsLHC95bJEzSN
|
|
625
629
|
|
|
626
630
|
<p align="center"><img src="https://raw.githubusercontent.com/KevRojo/Dulus/main/docs/divider.svg" alt="" width="100%"></p>
|
|
627
631
|
|
|
@@ -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.16-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"/>
|
|
@@ -45,6 +45,7 @@ SET /sticky_input ON since the first run for the best experience!
|
|
|
45
45
|
Talent cant be copied.
|
|
46
46
|
|
|
47
47
|
Dulus Reduce your IA costs by 60% parsing webchats and claude-code directly. Write poetry while Anthropic only see text.
|
|
48
|
+
Use claude-code as an API without the new 'extra-usage' wall <3
|
|
48
49
|
|
|
49
50
|
<p align="center"><img src="https://raw.githubusercontent.com/KevRojo/Dulus/main/docs/poetry-banner.png" alt="Anthropic only sees text while you and Claude are writing poetry" width="100%"></p>
|
|
50
51
|
|
|
@@ -577,6 +578,9 @@ git diff | dulus -p "write a commit message"
|
|
|
577
578
|
GPLv3. Fork it, modify it, redistribute it — but keep it open. Derivative works must stay under GPLv3. Just don't ship `--accept-all` as the default.
|
|
578
579
|
|
|
579
580
|
---
|
|
581
|
+
Donations:
|
|
582
|
+
|
|
583
|
+
Bitcoin: 1JzatQDn9fMLnKTd3KYgztsLHC95bJEzSN
|
|
580
584
|
|
|
581
585
|
<p align="center"><img src="https://raw.githubusercontent.com/KevRojo/Dulus/main/docs/divider.svg" alt="" width="100%"></p>
|
|
582
586
|
|
|
@@ -3,6 +3,14 @@
|
|
|
3
3
|
## 🔥🔥🔥 News (Pacific Time)
|
|
4
4
|
|
|
5
5
|
|
|
6
|
+
- May 09, 2026 (**v0.2.16**): **MemPalace per-session dedup — game changer**
|
|
7
|
+
- **No more re-injecting the same memory every turn.** MemPalace now keeps a per-session set of content-hashes (`_mp_injected_keys`) — once a memory is injected in this conversation, it won't be re-injected on later turns even if it scores high on a new query. The next-best non-duplicate hit is used instead, so each turn brings *new* context to the model rather than the same 3 hits over and over.
|
|
8
|
+
- **Within-turn dedup too.** When mempalace's hybrid retriever returns the same chunk twice in a single query (it happens), the duplicate is dropped before injection.
|
|
9
|
+
- **Why it's a game changer.** In a 20-turn conversation that previously kept re-injecting the same 3 memories, you save ≈8K tokens of duplicates AND the model gets ~30 distinct memories of palace coverage instead of just 3. Compounding context, no extra cost.
|
|
10
|
+
- **`/mem_palace reset`** — new sub-command to clear the dedup cache mid-session if you want already-seen memories to be re-injectable on the next match.
|
|
11
|
+
|
|
12
|
+
- May 09, 2026 (**v0.2.15**): Banner image hosted locally so PyPI renders it correctly.
|
|
13
|
+
|
|
6
14
|
- May 09, 2026 (**v0.2.14**): **Multi-user Telegram bridge**
|
|
7
15
|
- **Telegram bridge now supports multiple authorized chat_ids.** Configure with `/telegram <token> <id1>,<id2>,<id3>` or set `telegram_chat_ids` in `config.json` as a comma-separated string (trailing commas like `717151713,787615162,,` are ignored). Each authorized chat gets its own replies — Dulus tracks who sent each message via `_active_tg_chat_id` and routes the response back to the right user. Welcome message is broadcast to all configured users on bridge start. The legacy single-int `telegram_chat_id` still works for backwards-compat.
|
|
8
16
|
- **Why this matters.** One Dulus instance, multiple humans poking it from their phones — useful for teams sharing a long-running agent, or for paired-up users running the same MemPalace from different devices.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dulus
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.16
|
|
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
|
|
@@ -67,7 +67,7 @@ SET /sticky_input ON since the first run for the best experience!
|
|
|
67
67
|
<a href="https://pypi.org/project/dulus/"><img src="https://static.pepy.tech/badge/dulus?style=flat-square" alt="downloads"/></a>
|
|
68
68
|
<img src="https://img.shields.io/badge/python-3.11+-ff6b1f?style=flat-square&labelColor=07070a" alt="python"/>
|
|
69
69
|
<img src="https://img.shields.io/badge/license-GPLv3-ff6b1f?style=flat-square&labelColor=07070a" alt="license"/>
|
|
70
|
-
<img src="https://img.shields.io/badge/version-v0.2.
|
|
70
|
+
<img src="https://img.shields.io/badge/version-v0.2.16-ff6b1f?style=flat-square&labelColor=07070a" alt="version"/>
|
|
71
71
|
<img src="https://img.shields.io/badge/providers-11-ff6b1f?style=flat-square&labelColor=07070a" alt="providers"/>
|
|
72
72
|
<img src="https://img.shields.io/badge/tools-27-ff6b1f?style=flat-square&labelColor=07070a" alt="tools"/>
|
|
73
73
|
<img src="https://img.shields.io/badge/tests-263+-ff6b1f?style=flat-square&labelColor=07070a" alt="tests"/>
|
|
@@ -90,6 +90,7 @@ SET /sticky_input ON since the first run for the best experience!
|
|
|
90
90
|
Talent cant be copied.
|
|
91
91
|
|
|
92
92
|
Dulus Reduce your IA costs by 60% parsing webchats and claude-code directly. Write poetry while Anthropic only see text.
|
|
93
|
+
Use claude-code as an API without the new 'extra-usage' wall <3
|
|
93
94
|
|
|
94
95
|
<p align="center"><img src="https://raw.githubusercontent.com/KevRojo/Dulus/main/docs/poetry-banner.png" alt="Anthropic only sees text while you and Claude are writing poetry" width="100%"></p>
|
|
95
96
|
|
|
@@ -622,6 +623,9 @@ git diff | dulus -p "write a commit message"
|
|
|
622
623
|
GPLv3. Fork it, modify it, redistribute it — but keep it open. Derivative works must stay under GPLv3. Just don't ship `--accept-all` as the default.
|
|
623
624
|
|
|
624
625
|
---
|
|
626
|
+
Donations:
|
|
627
|
+
|
|
628
|
+
Bitcoin: 1JzatQDn9fMLnKTd3KYgztsLHC95bJEzSN
|
|
625
629
|
|
|
626
630
|
<p align="center"><img src="https://raw.githubusercontent.com/KevRojo/Dulus/main/docs/divider.svg" alt="" width="100%"></p>
|
|
627
631
|
|
|
@@ -1918,6 +1918,8 @@ def cmd_mem_palace(args: str, _state, config) -> bool:
|
|
|
1918
1918
|
/mem_palace → toggle the injection ON/OFF
|
|
1919
1919
|
/mem_palace print → toggle visibility: print to console what's being
|
|
1920
1920
|
injected to the model (debug — see klk pasa)
|
|
1921
|
+
/mem_palace reset → clear the per-session dedup cache (allows already-
|
|
1922
|
+
injected memories to be re-injected on next match)
|
|
1921
1923
|
|
|
1922
1924
|
ON → before each user turn, runs `search_memory(query=user_msg, k=3)`
|
|
1923
1925
|
via the mempalace plugin and injects the top hits as a system
|
|
@@ -1933,6 +1935,15 @@ def cmd_mem_palace(args: str, _state, config) -> bool:
|
|
|
1933
1935
|
ok(f"MemPalace injection-print (debug): {state_str}")
|
|
1934
1936
|
save_config(config)
|
|
1935
1937
|
return True
|
|
1938
|
+
if sub in ("reset", "clear", "forget"):
|
|
1939
|
+
# Clear the per-session dedup cache so memories injected earlier in
|
|
1940
|
+
# this conversation can be re-injected if they match a new query.
|
|
1941
|
+
n = len(config.get("_mp_injected_keys", set()))
|
|
1942
|
+
config["_mp_injected_keys"] = set()
|
|
1943
|
+
# also clear legacy name-based cache if present
|
|
1944
|
+
config.pop("_mp_injected_names", None)
|
|
1945
|
+
ok(f"MemPalace dedup cache cleared ({n} memories forgotten).")
|
|
1946
|
+
return True
|
|
1936
1947
|
config["mem_palace"] = not config.get("mem_palace", True)
|
|
1937
1948
|
state_str = "ON" if config["mem_palace"] else "OFF"
|
|
1938
1949
|
ok(f"MemPalace auto-injection: {state_str}")
|
|
@@ -7151,6 +7162,31 @@ def repl(config: dict, initial_prompt: str = None):
|
|
|
7151
7162
|
for _h in _raw_hits:
|
|
7152
7163
|
_mp_log(f" hit: score={float(_h.get('keyword_score', 0.0)):.3f} {_h.get('name','?')}", "dim")
|
|
7153
7164
|
_kept = [h for h in _raw_hits if float(h.get("keyword_score", 0.0)) >= _MIN_SCORE]
|
|
7165
|
+
# ── Dedup: skip memories already injected earlier in this session.
|
|
7166
|
+
# Key by content hash (not name) because mempalace often returns
|
|
7167
|
+
# generic names like "palace" for every hit in a wing — name-based
|
|
7168
|
+
# dedup would over-block. Content hash makes each memory unique.
|
|
7169
|
+
import hashlib as _hashlib
|
|
7170
|
+
def _mp_dedup_key(h):
|
|
7171
|
+
content = (h.get("content") or "").strip()[:240]
|
|
7172
|
+
return _hashlib.md5(content.encode("utf-8", errors="ignore")).hexdigest()[:12]
|
|
7173
|
+
_seen = config.setdefault("_mp_injected_keys", set())
|
|
7174
|
+
_before_dedup = len(_kept)
|
|
7175
|
+
# Dedup against session cache AND within this turn's hits
|
|
7176
|
+
# (mempalace sometimes returns the same chunk twice in one query).
|
|
7177
|
+
_this_turn = set()
|
|
7178
|
+
_filtered = []
|
|
7179
|
+
for _h in _kept:
|
|
7180
|
+
_k = _mp_dedup_key(_h)
|
|
7181
|
+
if _k in _seen or _k in _this_turn:
|
|
7182
|
+
continue
|
|
7183
|
+
_this_turn.add(_k)
|
|
7184
|
+
_filtered.append(_h)
|
|
7185
|
+
_kept = _filtered
|
|
7186
|
+
if _before_dedup and not _kept:
|
|
7187
|
+
_mp_log(f"skip: all {_before_dedup} hits already injected this session", "dim")
|
|
7188
|
+
elif _before_dedup != len(_kept):
|
|
7189
|
+
_mp_log(f"dedup: dropped {_before_dedup - len(_kept)} already-injected memories", "dim")
|
|
7154
7190
|
if not _kept:
|
|
7155
7191
|
_mp_log(f"skip: no hits above threshold {_MIN_SCORE} (raw={len(_raw_hits)})", "dim")
|
|
7156
7192
|
else:
|
|
@@ -7182,6 +7218,9 @@ def repl(config: dict, initial_prompt: str = None):
|
|
|
7182
7218
|
+ "\n\n---\n\n[USER MESSAGE]\n"
|
|
7183
7219
|
+ user_input
|
|
7184
7220
|
)
|
|
7221
|
+
# Mark these as injected so we don't repeat them next turn.
|
|
7222
|
+
for _h in _kept:
|
|
7223
|
+
_seen.add(_mp_dedup_key(_h))
|
|
7185
7224
|
if _mp_dbg:
|
|
7186
7225
|
print(clr(
|
|
7187
7226
|
f"\n ── [MemPalace inject → {len(_inject)} chars] ──",
|
|
@@ -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.16"
|
|
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
|