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.
Files changed (157) hide show
  1. {dulus-0.2.15/dulus.egg-info → dulus-0.2.16}/PKG-INFO +6 -2
  2. {dulus-0.2.15 → dulus-0.2.16}/README.md +5 -1
  3. {dulus-0.2.15 → dulus-0.2.16}/docs/news.md +8 -0
  4. {dulus-0.2.15 → dulus-0.2.16/dulus.egg-info}/PKG-INFO +6 -2
  5. {dulus-0.2.15 → dulus-0.2.16}/dulus.py +39 -0
  6. {dulus-0.2.15 → dulus-0.2.16}/pyproject.toml +1 -1
  7. {dulus-0.2.15 → dulus-0.2.16}/LICENSE +0 -0
  8. {dulus-0.2.15 → dulus-0.2.16}/MANIFEST.in +0 -0
  9. {dulus-0.2.15 → dulus-0.2.16}/agent.py +0 -0
  10. {dulus-0.2.15 → dulus-0.2.16}/backend/__init__.py +0 -0
  11. {dulus-0.2.15 → dulus-0.2.16}/backend/compressor.py +0 -0
  12. {dulus-0.2.15 → dulus-0.2.16}/backend/context.py +0 -0
  13. {dulus-0.2.15 → dulus-0.2.16}/backend/githook.py +0 -0
  14. {dulus-0.2.15 → dulus-0.2.16}/backend/marketplace.py +0 -0
  15. {dulus-0.2.15 → dulus-0.2.16}/backend/mempalace_bridge.py +0 -0
  16. {dulus-0.2.15 → dulus-0.2.16}/backend/personas.py +0 -0
  17. {dulus-0.2.15 → dulus-0.2.16}/backend/plugins.py +0 -0
  18. {dulus-0.2.15 → dulus-0.2.16}/backend/server.py +0 -0
  19. {dulus-0.2.15 → dulus-0.2.16}/backend/tasks.py +0 -0
  20. {dulus-0.2.15 → dulus-0.2.16}/batch_api.py +0 -0
  21. {dulus-0.2.15 → dulus-0.2.16}/checkpoint/__init__.py +0 -0
  22. {dulus-0.2.15 → dulus-0.2.16}/checkpoint/hooks.py +0 -0
  23. {dulus-0.2.15 → dulus-0.2.16}/checkpoint/store.py +0 -0
  24. {dulus-0.2.15 → dulus-0.2.16}/checkpoint/types.py +0 -0
  25. {dulus-0.2.15 → dulus-0.2.16}/claude_code_watcher.py +0 -0
  26. {dulus-0.2.15 → dulus-0.2.16}/clipboard_utils.py +0 -0
  27. {dulus-0.2.15 → dulus-0.2.16}/cloudsave.py +0 -0
  28. {dulus-0.2.15 → dulus-0.2.16}/common.py +0 -0
  29. {dulus-0.2.15 → dulus-0.2.16}/compaction.py +0 -0
  30. {dulus-0.2.15 → dulus-0.2.16}/config.py +0 -0
  31. {dulus-0.2.15 → dulus-0.2.16}/context.py +0 -0
  32. {dulus-0.2.15 → dulus-0.2.16}/data/__init__.py +0 -0
  33. {dulus-0.2.15 → dulus-0.2.16}/data/active_persona.json +0 -0
  34. {dulus-0.2.15 → dulus-0.2.16}/data/context.json +0 -0
  35. {dulus-0.2.15 → dulus-0.2.16}/data/marketplace.json +0 -0
  36. {dulus-0.2.15 → dulus-0.2.16}/data/personas.json +0 -0
  37. {dulus-0.2.15 → dulus-0.2.16}/data/tasks.json +0 -0
  38. {dulus-0.2.15 → dulus-0.2.16}/docs/README.md +0 -0
  39. {dulus-0.2.15 → dulus-0.2.16}/docs/__init__.py +0 -0
  40. {dulus-0.2.15 → dulus-0.2.16}/docs/api.html +0 -0
  41. {dulus-0.2.15 → dulus-0.2.16}/docs/architecture.md +0 -0
  42. {dulus-0.2.15 → dulus-0.2.16}/docs/azure-speech-template.json +0 -0
  43. {dulus-0.2.15 → dulus-0.2.16}/docs/dashboard/index.html +0 -0
  44. {dulus-0.2.15 → dulus-0.2.16}/docs/divider.svg +0 -0
  45. {dulus-0.2.15 → dulus-0.2.16}/docs/generate.py +0 -0
  46. {dulus-0.2.15 → dulus-0.2.16}/docs/hero.svg +0 -0
  47. {dulus-0.2.15 → dulus-0.2.16}/docs/index.html +0 -0
  48. {dulus-0.2.15 → dulus-0.2.16}/docs/nvidia-models.svg +0 -0
  49. {dulus-0.2.15 → dulus-0.2.16}/docs/particle-playground.html +0 -0
  50. {dulus-0.2.15 → dulus-0.2.16}/docs/personas/index.html +0 -0
  51. {dulus-0.2.15 → dulus-0.2.16}/docs/poetry-banner.png +0 -0
  52. {dulus-0.2.15 → dulus-0.2.16}/docs/preview.html +0 -0
  53. {dulus-0.2.15 → dulus-0.2.16}/docs/sec-agents.svg +0 -0
  54. {dulus-0.2.15 → dulus-0.2.16}/docs/sec-brainstorm.svg +0 -0
  55. {dulus-0.2.15 → dulus-0.2.16}/docs/sec-bridges.svg +0 -0
  56. {dulus-0.2.15 → dulus-0.2.16}/docs/sec-features.svg +0 -0
  57. {dulus-0.2.15 → dulus-0.2.16}/docs/sec-freetier.svg +0 -0
  58. {dulus-0.2.15 → dulus-0.2.16}/docs/sec-memory.svg +0 -0
  59. {dulus-0.2.15 → dulus-0.2.16}/docs/sec-models.svg +0 -0
  60. {dulus-0.2.15 → dulus-0.2.16}/docs/sec-perms.svg +0 -0
  61. {dulus-0.2.15 → dulus-0.2.16}/docs/sec-plugins.svg +0 -0
  62. {dulus-0.2.15 → dulus-0.2.16}/docs/sec-quickstart.svg +0 -0
  63. {dulus-0.2.15 → dulus-0.2.16}/docs/sec-ssj.svg +0 -0
  64. {dulus-0.2.15 → dulus-0.2.16}/docs/spinners.svg +0 -0
  65. {dulus-0.2.15 → dulus-0.2.16}/docs/split-pane.svg +0 -0
  66. {dulus-0.2.15 → dulus-0.2.16}/docs/terminal-boot.svg +0 -0
  67. {dulus-0.2.15 → dulus-0.2.16}/docs/uploads/particle-playground.html +0 -0
  68. {dulus-0.2.15 → dulus-0.2.16}/dulus.egg-info/SOURCES.txt +0 -0
  69. {dulus-0.2.15 → dulus-0.2.16}/dulus.egg-info/dependency_links.txt +0 -0
  70. {dulus-0.2.15 → dulus-0.2.16}/dulus.egg-info/entry_points.txt +0 -0
  71. {dulus-0.2.15 → dulus-0.2.16}/dulus.egg-info/requires.txt +0 -0
  72. {dulus-0.2.15 → dulus-0.2.16}/dulus.egg-info/top_level.txt +0 -0
  73. {dulus-0.2.15 → dulus-0.2.16}/dulus_gui.py +0 -0
  74. {dulus-0.2.15 → dulus-0.2.16}/dulus_mcp/__init__.py +0 -0
  75. {dulus-0.2.15 → dulus-0.2.16}/dulus_mcp/client.py +0 -0
  76. {dulus-0.2.15 → dulus-0.2.16}/dulus_mcp/config.py +0 -0
  77. {dulus-0.2.15 → dulus-0.2.16}/dulus_mcp/tools.py +0 -0
  78. {dulus-0.2.15 → dulus-0.2.16}/dulus_mcp/types.py +0 -0
  79. {dulus-0.2.15 → dulus-0.2.16}/gui/__init__.py +0 -0
  80. {dulus-0.2.15 → dulus-0.2.16}/gui/agent_bridge.py +0 -0
  81. {dulus-0.2.15 → dulus-0.2.16}/gui/chat_widget.py +0 -0
  82. {dulus-0.2.15 → dulus-0.2.16}/gui/main_window.py +0 -0
  83. {dulus-0.2.15 → dulus-0.2.16}/gui/personas.py +0 -0
  84. {dulus-0.2.15 → dulus-0.2.16}/gui/session_utils.py +0 -0
  85. {dulus-0.2.15 → dulus-0.2.16}/gui/settings_dialog.py +0 -0
  86. {dulus-0.2.15 → dulus-0.2.16}/gui/sidebar.py +0 -0
  87. {dulus-0.2.15 → dulus-0.2.16}/gui/tasks_view.py +0 -0
  88. {dulus-0.2.15 → dulus-0.2.16}/gui/themes.py +0 -0
  89. {dulus-0.2.15 → dulus-0.2.16}/gui/tool_panel.py +0 -0
  90. {dulus-0.2.15 → dulus-0.2.16}/input.py +0 -0
  91. {dulus-0.2.15 → dulus-0.2.16}/license_manager.py +0 -0
  92. {dulus-0.2.15 → dulus-0.2.16}/memory/__init__.py +0 -0
  93. {dulus-0.2.15 → dulus-0.2.16}/memory/audit.py +0 -0
  94. {dulus-0.2.15 → dulus-0.2.16}/memory/consolidator.py +0 -0
  95. {dulus-0.2.15 → dulus-0.2.16}/memory/context.py +0 -0
  96. {dulus-0.2.15 → dulus-0.2.16}/memory/offload.py +0 -0
  97. {dulus-0.2.15 → dulus-0.2.16}/memory/palace.py +0 -0
  98. {dulus-0.2.15 → dulus-0.2.16}/memory/scan.py +0 -0
  99. {dulus-0.2.15 → dulus-0.2.16}/memory/sessions.py +0 -0
  100. {dulus-0.2.15 → dulus-0.2.16}/memory/store.py +0 -0
  101. {dulus-0.2.15 → dulus-0.2.16}/memory/tools.py +0 -0
  102. {dulus-0.2.15 → dulus-0.2.16}/memory/types.py +0 -0
  103. {dulus-0.2.15 → dulus-0.2.16}/memory/vector_search.py +0 -0
  104. {dulus-0.2.15 → dulus-0.2.16}/multi_agent/__init__.py +0 -0
  105. {dulus-0.2.15 → dulus-0.2.16}/multi_agent/subagent.py +0 -0
  106. {dulus-0.2.15 → dulus-0.2.16}/multi_agent/tools.py +0 -0
  107. {dulus-0.2.15 → dulus-0.2.16}/offload_helper.py +0 -0
  108. {dulus-0.2.15 → dulus-0.2.16}/plugin/__init__.py +0 -0
  109. {dulus-0.2.15 → dulus-0.2.16}/plugin/autoadapter.py +0 -0
  110. {dulus-0.2.15 → dulus-0.2.16}/plugin/loader.py +0 -0
  111. {dulus-0.2.15 → dulus-0.2.16}/plugin/recommend.py +0 -0
  112. {dulus-0.2.15 → dulus-0.2.16}/plugin/store.py +0 -0
  113. {dulus-0.2.15 → dulus-0.2.16}/plugin/types.py +0 -0
  114. {dulus-0.2.15 → dulus-0.2.16}/providers.py +0 -0
  115. {dulus-0.2.15 → dulus-0.2.16}/setup.cfg +0 -0
  116. {dulus-0.2.15 → dulus-0.2.16}/skill/__init__.py +0 -0
  117. {dulus-0.2.15 → dulus-0.2.16}/skill/builtin.py +0 -0
  118. {dulus-0.2.15 → dulus-0.2.16}/skill/clawhub.py +0 -0
  119. {dulus-0.2.15 → dulus-0.2.16}/skill/executor.py +0 -0
  120. {dulus-0.2.15 → dulus-0.2.16}/skill/loader.py +0 -0
  121. {dulus-0.2.15 → dulus-0.2.16}/skill/tools.py +0 -0
  122. {dulus-0.2.15 → dulus-0.2.16}/skills.py +0 -0
  123. {dulus-0.2.15 → dulus-0.2.16}/spinner.py +0 -0
  124. {dulus-0.2.15 → dulus-0.2.16}/string_utils.py +0 -0
  125. {dulus-0.2.15 → dulus-0.2.16}/subagent.py +0 -0
  126. {dulus-0.2.15 → dulus-0.2.16}/task/__init__.py +0 -0
  127. {dulus-0.2.15 → dulus-0.2.16}/task/store.py +0 -0
  128. {dulus-0.2.15 → dulus-0.2.16}/task/tools.py +0 -0
  129. {dulus-0.2.15 → dulus-0.2.16}/task/types.py +0 -0
  130. {dulus-0.2.15 → dulus-0.2.16}/tests/test_checkpoint.py +0 -0
  131. {dulus-0.2.15 → dulus-0.2.16}/tests/test_compaction.py +0 -0
  132. {dulus-0.2.15 → dulus-0.2.16}/tests/test_diff_view.py +0 -0
  133. {dulus-0.2.15 → dulus-0.2.16}/tests/test_injection_fix.py +0 -0
  134. {dulus-0.2.15 → dulus-0.2.16}/tests/test_license.py +0 -0
  135. {dulus-0.2.15 → dulus-0.2.16}/tests/test_mcp.py +0 -0
  136. {dulus-0.2.15 → dulus-0.2.16}/tests/test_memory.py +0 -0
  137. {dulus-0.2.15 → dulus-0.2.16}/tests/test_plugin.py +0 -0
  138. {dulus-0.2.15 → dulus-0.2.16}/tests/test_skills.py +0 -0
  139. {dulus-0.2.15 → dulus-0.2.16}/tests/test_subagent.py +0 -0
  140. {dulus-0.2.15 → dulus-0.2.16}/tests/test_task.py +0 -0
  141. {dulus-0.2.15 → dulus-0.2.16}/tests/test_telegram_buffer.py +0 -0
  142. {dulus-0.2.15 → dulus-0.2.16}/tests/test_tool_registry.py +0 -0
  143. {dulus-0.2.15 → dulus-0.2.16}/tests/test_voice.py +0 -0
  144. {dulus-0.2.15 → dulus-0.2.16}/tmux_offloader.py +0 -0
  145. {dulus-0.2.15 → dulus-0.2.16}/tmux_tools.py +0 -0
  146. {dulus-0.2.15 → dulus-0.2.16}/tool_registry.py +0 -0
  147. {dulus-0.2.15 → dulus-0.2.16}/tools.py +0 -0
  148. {dulus-0.2.15 → dulus-0.2.16}/ui/__init__.py +0 -0
  149. {dulus-0.2.15 → dulus-0.2.16}/ui/input.py +0 -0
  150. {dulus-0.2.15 → dulus-0.2.16}/ui/render.py +0 -0
  151. {dulus-0.2.15 → dulus-0.2.16}/voice/__init__.py +0 -0
  152. {dulus-0.2.15 → dulus-0.2.16}/voice/keyterms.py +0 -0
  153. {dulus-0.2.15 → dulus-0.2.16}/voice/recorder.py +0 -0
  154. {dulus-0.2.15 → dulus-0.2.16}/voice/stt.py +0 -0
  155. {dulus-0.2.15 → dulus-0.2.16}/voice/tts.py +0 -0
  156. {dulus-0.2.15 → dulus-0.2.16}/webchat.py +0 -0
  157. {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.15
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.15-ff6b1f?style=flat-square&labelColor=07070a" alt="version"/>
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.15-ff6b1f?style=flat-square&labelColor=07070a" alt="version"/>
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.15
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.15-ff6b1f?style=flat-square&labelColor=07070a" alt="version"/>
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.15"
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