dulus 0.2.41__tar.gz → 0.2.42__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 (181) hide show
  1. {dulus-0.2.41/dulus.egg-info → dulus-0.2.42}/PKG-INFO +9 -2
  2. {dulus-0.2.41 → dulus-0.2.42}/README.md +8 -1
  3. {dulus-0.2.41 → dulus-0.2.42}/common.py +1 -1
  4. {dulus-0.2.41 → dulus-0.2.42}/data/context.json +42 -12
  5. {dulus-0.2.41 → dulus-0.2.42/dulus.egg-info}/PKG-INFO +9 -2
  6. {dulus-0.2.41 → dulus-0.2.42}/dulus.py +45 -1
  7. {dulus-0.2.41 → dulus-0.2.42}/pyproject.toml +1 -1
  8. {dulus-0.2.41 → dulus-0.2.42}/task/store.py +10 -0
  9. {dulus-0.2.41 → dulus-0.2.42}/task/tools.py +17 -6
  10. {dulus-0.2.41 → dulus-0.2.42}/tools.py +39 -0
  11. {dulus-0.2.41 → dulus-0.2.42}/webchat_server.py +223 -44
  12. {dulus-0.2.41 → dulus-0.2.42}/LICENSE +0 -0
  13. {dulus-0.2.41 → dulus-0.2.42}/MANIFEST.in +0 -0
  14. {dulus-0.2.41 → dulus-0.2.42}/agent.py +0 -0
  15. {dulus-0.2.41 → dulus-0.2.42}/backend/__init__.py +0 -0
  16. {dulus-0.2.41 → dulus-0.2.42}/backend/compressor.py +0 -0
  17. {dulus-0.2.41 → dulus-0.2.42}/backend/context.py +0 -0
  18. {dulus-0.2.41 → dulus-0.2.42}/backend/githook.py +0 -0
  19. {dulus-0.2.41 → dulus-0.2.42}/backend/marketplace.py +0 -0
  20. {dulus-0.2.41 → dulus-0.2.42}/backend/mempalace_bridge.py +0 -0
  21. {dulus-0.2.41 → dulus-0.2.42}/backend/personas.py +0 -0
  22. {dulus-0.2.41 → dulus-0.2.42}/backend/plugins.py +0 -0
  23. {dulus-0.2.41 → dulus-0.2.42}/backend/server.py +0 -0
  24. {dulus-0.2.41 → dulus-0.2.42}/backend/tasks.py +0 -0
  25. {dulus-0.2.41 → dulus-0.2.42}/batch_api.py +0 -0
  26. {dulus-0.2.41 → dulus-0.2.42}/checkpoint/__init__.py +0 -0
  27. {dulus-0.2.41 → dulus-0.2.42}/checkpoint/hooks.py +0 -0
  28. {dulus-0.2.41 → dulus-0.2.42}/checkpoint/store.py +0 -0
  29. {dulus-0.2.41 → dulus-0.2.42}/checkpoint/types.py +0 -0
  30. {dulus-0.2.41 → dulus-0.2.42}/claude_code_watcher.py +0 -0
  31. {dulus-0.2.41 → dulus-0.2.42}/clipboard_utils.py +0 -0
  32. {dulus-0.2.41 → dulus-0.2.42}/cloudsave.py +0 -0
  33. {dulus-0.2.41 → dulus-0.2.42}/compaction.py +0 -0
  34. {dulus-0.2.41 → dulus-0.2.42}/config.py +0 -0
  35. {dulus-0.2.41 → dulus-0.2.42}/context.py +0 -0
  36. {dulus-0.2.41 → dulus-0.2.42}/data/__init__.py +0 -0
  37. {dulus-0.2.41 → dulus-0.2.42}/data/active_persona.json +0 -0
  38. {dulus-0.2.41 → dulus-0.2.42}/data/marketplace.json +0 -0
  39. {dulus-0.2.41 → dulus-0.2.42}/data/personas.json +0 -0
  40. {dulus-0.2.41 → dulus-0.2.42}/data/plugins/__init__.py +0 -0
  41. {dulus-0.2.41 → dulus-0.2.42}/data/plugins/composio/__init__.py +0 -0
  42. {dulus-0.2.41 → dulus-0.2.42}/data/plugins/composio/composio_plugin/__init__.py +0 -0
  43. {dulus-0.2.41 → dulus-0.2.42}/data/plugins/composio/composio_plugin/session_manager.py +0 -0
  44. {dulus-0.2.41 → dulus-0.2.42}/data/plugins/composio/composio_plugin/tool_generator.py +0 -0
  45. {dulus-0.2.41 → dulus-0.2.42}/data/plugins/composio/plugin.json +0 -0
  46. {dulus-0.2.41 → dulus-0.2.42}/data/plugins/composio/plugin_tool.py +0 -0
  47. {dulus-0.2.41 → dulus-0.2.42}/data/tasks.json +0 -0
  48. {dulus-0.2.41 → dulus-0.2.42}/docs/README.md +0 -0
  49. {dulus-0.2.41 → dulus-0.2.42}/docs/__init__.py +0 -0
  50. {dulus-0.2.41 → dulus-0.2.42}/docs/api.html +0 -0
  51. {dulus-0.2.41 → dulus-0.2.42}/docs/architecture.md +0 -0
  52. {dulus-0.2.41 → dulus-0.2.42}/docs/azure-speech-template.json +0 -0
  53. {dulus-0.2.41 → dulus-0.2.42}/docs/dashboard/index.html +0 -0
  54. {dulus-0.2.41 → dulus-0.2.42}/docs/divider.svg +0 -0
  55. {dulus-0.2.41 → dulus-0.2.42}/docs/generate.py +0 -0
  56. {dulus-0.2.41 → dulus-0.2.42}/docs/hero.svg +0 -0
  57. {dulus-0.2.41 → dulus-0.2.42}/docs/index.html +0 -0
  58. {dulus-0.2.41 → dulus-0.2.42}/docs/news.md +0 -0
  59. {dulus-0.2.41 → dulus-0.2.42}/docs/nvidia-models.svg +0 -0
  60. {dulus-0.2.41 → dulus-0.2.42}/docs/particle-playground.html +0 -0
  61. {dulus-0.2.41 → dulus-0.2.42}/docs/personas/index.html +0 -0
  62. {dulus-0.2.41 → dulus-0.2.42}/docs/poetry-banner.png +0 -0
  63. {dulus-0.2.41 → dulus-0.2.42}/docs/preview.html +0 -0
  64. {dulus-0.2.41 → dulus-0.2.42}/docs/sec-agents.svg +0 -0
  65. {dulus-0.2.41 → dulus-0.2.42}/docs/sec-brainstorm.svg +0 -0
  66. {dulus-0.2.41 → dulus-0.2.42}/docs/sec-bridges.svg +0 -0
  67. {dulus-0.2.41 → dulus-0.2.42}/docs/sec-features.svg +0 -0
  68. {dulus-0.2.41 → dulus-0.2.42}/docs/sec-freetier.svg +0 -0
  69. {dulus-0.2.41 → dulus-0.2.42}/docs/sec-memory.svg +0 -0
  70. {dulus-0.2.41 → dulus-0.2.42}/docs/sec-models.svg +0 -0
  71. {dulus-0.2.41 → dulus-0.2.42}/docs/sec-perms.svg +0 -0
  72. {dulus-0.2.41 → dulus-0.2.42}/docs/sec-plugins.svg +0 -0
  73. {dulus-0.2.41 → dulus-0.2.42}/docs/sec-quickstart.svg +0 -0
  74. {dulus-0.2.41 → dulus-0.2.42}/docs/sec-ssj.svg +0 -0
  75. {dulus-0.2.41 → dulus-0.2.42}/docs/spinners.svg +0 -0
  76. {dulus-0.2.41 → dulus-0.2.42}/docs/split-pane.svg +0 -0
  77. {dulus-0.2.41 → dulus-0.2.42}/docs/terminal-boot.svg +0 -0
  78. {dulus-0.2.41 → dulus-0.2.42}/docs/uploads/particle-playground.html +0 -0
  79. {dulus-0.2.41 → dulus-0.2.42}/dulus.egg-info/SOURCES.txt +0 -0
  80. {dulus-0.2.41 → dulus-0.2.42}/dulus.egg-info/dependency_links.txt +0 -0
  81. {dulus-0.2.41 → dulus-0.2.42}/dulus.egg-info/entry_points.txt +0 -0
  82. {dulus-0.2.41 → dulus-0.2.42}/dulus.egg-info/requires.txt +0 -0
  83. {dulus-0.2.41 → dulus-0.2.42}/dulus.egg-info/top_level.txt +0 -0
  84. {dulus-0.2.41 → dulus-0.2.42}/dulus_gui.py +0 -0
  85. {dulus-0.2.41 → dulus-0.2.42}/dulus_mcp/__init__.py +0 -0
  86. {dulus-0.2.41 → dulus-0.2.42}/dulus_mcp/client.py +0 -0
  87. {dulus-0.2.41 → dulus-0.2.42}/dulus_mcp/config.py +0 -0
  88. {dulus-0.2.41 → dulus-0.2.42}/dulus_mcp/tools.py +0 -0
  89. {dulus-0.2.41 → dulus-0.2.42}/dulus_mcp/types.py +0 -0
  90. {dulus-0.2.41 → dulus-0.2.42}/gui/__init__.py +0 -0
  91. {dulus-0.2.41 → dulus-0.2.42}/gui/agent_bridge.py +0 -0
  92. {dulus-0.2.41 → dulus-0.2.42}/gui/chat_widget.py +0 -0
  93. {dulus-0.2.41 → dulus-0.2.42}/gui/main_window.py +0 -0
  94. {dulus-0.2.41 → dulus-0.2.42}/gui/personas.py +0 -0
  95. {dulus-0.2.41 → dulus-0.2.42}/gui/session_utils.py +0 -0
  96. {dulus-0.2.41 → dulus-0.2.42}/gui/settings_dialog.py +0 -0
  97. {dulus-0.2.41 → dulus-0.2.42}/gui/sidebar.py +0 -0
  98. {dulus-0.2.41 → dulus-0.2.42}/gui/tasks_view.py +0 -0
  99. {dulus-0.2.41 → dulus-0.2.42}/gui/themes.py +0 -0
  100. {dulus-0.2.41 → dulus-0.2.42}/gui/tool_panel.py +0 -0
  101. {dulus-0.2.41 → dulus-0.2.42}/input.py +0 -0
  102. {dulus-0.2.41 → dulus-0.2.42}/license_manager.py +0 -0
  103. {dulus-0.2.41 → dulus-0.2.42}/memory/__init__.py +0 -0
  104. {dulus-0.2.41 → dulus-0.2.42}/memory/audit.py +0 -0
  105. {dulus-0.2.41 → dulus-0.2.42}/memory/consolidator.py +0 -0
  106. {dulus-0.2.41 → dulus-0.2.42}/memory/context.py +0 -0
  107. {dulus-0.2.41 → dulus-0.2.42}/memory/offload.py +0 -0
  108. {dulus-0.2.41 → dulus-0.2.42}/memory/palace.py +0 -0
  109. {dulus-0.2.41 → dulus-0.2.42}/memory/scan.py +0 -0
  110. {dulus-0.2.41 → dulus-0.2.42}/memory/sessions.py +0 -0
  111. {dulus-0.2.41 → dulus-0.2.42}/memory/store.py +0 -0
  112. {dulus-0.2.41 → dulus-0.2.42}/memory/tools.py +0 -0
  113. {dulus-0.2.41 → dulus-0.2.42}/memory/types.py +0 -0
  114. {dulus-0.2.41 → dulus-0.2.42}/memory/vector_search.py +0 -0
  115. {dulus-0.2.41 → dulus-0.2.42}/multi_agent/__init__.py +0 -0
  116. {dulus-0.2.41 → dulus-0.2.42}/multi_agent/subagent.py +0 -0
  117. {dulus-0.2.41 → dulus-0.2.42}/multi_agent/tools.py +0 -0
  118. {dulus-0.2.41 → dulus-0.2.42}/offload_helper.py +0 -0
  119. {dulus-0.2.41 → dulus-0.2.42}/plugin/__init__.py +0 -0
  120. {dulus-0.2.41 → dulus-0.2.42}/plugin/autoadapter.py +0 -0
  121. {dulus-0.2.41 → dulus-0.2.42}/plugin/loader.py +0 -0
  122. {dulus-0.2.41 → dulus-0.2.42}/plugin/recommend.py +0 -0
  123. {dulus-0.2.41 → dulus-0.2.42}/plugin/store.py +0 -0
  124. {dulus-0.2.41 → dulus-0.2.42}/plugin/types.py +0 -0
  125. {dulus-0.2.41 → dulus-0.2.42}/providers.py +0 -0
  126. {dulus-0.2.41 → dulus-0.2.42}/setup.cfg +0 -0
  127. {dulus-0.2.41 → dulus-0.2.42}/skill/__init__.py +0 -0
  128. {dulus-0.2.41 → dulus-0.2.42}/skill/builtin.py +0 -0
  129. {dulus-0.2.41 → dulus-0.2.42}/skill/clawhub.py +0 -0
  130. {dulus-0.2.41 → dulus-0.2.42}/skill/executor.py +0 -0
  131. {dulus-0.2.41 → dulus-0.2.42}/skill/loader.py +0 -0
  132. {dulus-0.2.41 → dulus-0.2.42}/skill/tools.py +0 -0
  133. {dulus-0.2.41 → dulus-0.2.42}/skills.py +0 -0
  134. {dulus-0.2.41 → dulus-0.2.42}/spinner.py +0 -0
  135. {dulus-0.2.41 → dulus-0.2.42}/string_utils.py +0 -0
  136. {dulus-0.2.41 → dulus-0.2.42}/subagent.py +0 -0
  137. {dulus-0.2.41 → dulus-0.2.42}/task/__init__.py +0 -0
  138. {dulus-0.2.41 → dulus-0.2.42}/task/types.py +0 -0
  139. {dulus-0.2.41 → dulus-0.2.42}/tests/test_afk_yolo.py +0 -0
  140. {dulus-0.2.41 → dulus-0.2.42}/tests/test_approval_runtime.py +0 -0
  141. {dulus-0.2.41 → dulus-0.2.42}/tests/test_background_task_tools.py +0 -0
  142. {dulus-0.2.41 → dulus-0.2.42}/tests/test_background_tasks.py +0 -0
  143. {dulus-0.2.41 → dulus-0.2.42}/tests/test_checkpoint.py +0 -0
  144. {dulus-0.2.41 → dulus-0.2.42}/tests/test_clipboard_utils.py +0 -0
  145. {dulus-0.2.41 → dulus-0.2.42}/tests/test_compaction.py +0 -0
  146. {dulus-0.2.41 → dulus-0.2.42}/tests/test_diff_view.py +0 -0
  147. {dulus-0.2.41 → dulus-0.2.42}/tests/test_diff_visualization.py +0 -0
  148. {dulus-0.2.41 → dulus-0.2.42}/tests/test_display_blocks.py +0 -0
  149. {dulus-0.2.41 → dulus-0.2.42}/tests/test_export_import.py +0 -0
  150. {dulus-0.2.41 → dulus-0.2.42}/tests/test_hook_engine.py +0 -0
  151. {dulus-0.2.41 → dulus-0.2.42}/tests/test_injection_fix.py +0 -0
  152. {dulus-0.2.41 → dulus-0.2.42}/tests/test_license.py +0 -0
  153. {dulus-0.2.41 → dulus-0.2.42}/tests/test_mcp.py +0 -0
  154. {dulus-0.2.41 → dulus-0.2.42}/tests/test_memory.py +0 -0
  155. {dulus-0.2.41 → dulus-0.2.42}/tests/test_notification_manager.py +0 -0
  156. {dulus-0.2.41 → dulus-0.2.42}/tests/test_plugin.py +0 -0
  157. {dulus-0.2.41 → dulus-0.2.42}/tests/test_session_fork.py +0 -0
  158. {dulus-0.2.41 → dulus-0.2.42}/tests/test_shell_mode.py +0 -0
  159. {dulus-0.2.41 → dulus-0.2.42}/tests/test_skills.py +0 -0
  160. {dulus-0.2.41 → dulus-0.2.42}/tests/test_steer_input.py +0 -0
  161. {dulus-0.2.41 → dulus-0.2.42}/tests/test_subagent.py +0 -0
  162. {dulus-0.2.41 → dulus-0.2.42}/tests/test_task.py +0 -0
  163. {dulus-0.2.41 → dulus-0.2.42}/tests/test_telegram_buffer.py +0 -0
  164. {dulus-0.2.41 → dulus-0.2.42}/tests/test_think_tool.py +0 -0
  165. {dulus-0.2.41 → dulus-0.2.42}/tests/test_todo_tool.py +0 -0
  166. {dulus-0.2.41 → dulus-0.2.42}/tests/test_todo_visualization.py +0 -0
  167. {dulus-0.2.41 → dulus-0.2.42}/tests/test_tool_registry.py +0 -0
  168. {dulus-0.2.41 → dulus-0.2.42}/tests/test_voice.py +0 -0
  169. {dulus-0.2.41 → dulus-0.2.42}/tests/test_wire_events.py +0 -0
  170. {dulus-0.2.41 → dulus-0.2.42}/tmux_offloader.py +0 -0
  171. {dulus-0.2.41 → dulus-0.2.42}/tmux_tools.py +0 -0
  172. {dulus-0.2.41 → dulus-0.2.42}/tool_registry.py +0 -0
  173. {dulus-0.2.41 → dulus-0.2.42}/ui/__init__.py +0 -0
  174. {dulus-0.2.41 → dulus-0.2.42}/ui/input.py +0 -0
  175. {dulus-0.2.41 → dulus-0.2.42}/ui/render.py +0 -0
  176. {dulus-0.2.41 → dulus-0.2.42}/voice/__init__.py +0 -0
  177. {dulus-0.2.41 → dulus-0.2.42}/voice/keyterms.py +0 -0
  178. {dulus-0.2.41 → dulus-0.2.42}/voice/recorder.py +0 -0
  179. {dulus-0.2.41 → dulus-0.2.42}/voice/stt.py +0 -0
  180. {dulus-0.2.41 → dulus-0.2.42}/voice/tts.py +0 -0
  181. {dulus-0.2.41 → dulus-0.2.42}/webchat.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dulus
3
- Version: 0.2.41
3
+ Version: 0.2.42
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.30-ff6b1f?style=flat-square&labelColor=07070a" alt="version"/>
72
+ <img src="https://img.shields.io/badge/version-v0.2.42-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"/>
@@ -227,6 +227,13 @@ echo "explain this diff" | git diff | dulus -p --accept-all
227
227
 
228
228
  <p align="center"><sub>↑ session boot. soul loaded, gold memory warm, shell sniffed. the little circles are real buttons on your Mac.</sub></p>
229
229
 
230
+ ### 💻 Dulus OS (Sandbox)
231
+ > [!NOTE]
232
+ > **Experimental features:** The folder `sandbox/` contains the early implementation of **Dulus OS** — a mini-operating system that runs entirely in your browser. It is currently in heavy development and not 100% functional yet. It will serve as a secure, isolated environment for browser-based tool execution and visualizations.
233
+
234
+ ---
235
+
236
+
230
237
  ---
231
238
 
232
239
  <p align="center"><img src="https://raw.githubusercontent.com/KevRojo/Dulus/main/docs/sec-features.svg" alt="Features" width="100%"></p>
@@ -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.30-ff6b1f?style=flat-square&labelColor=07070a" alt="version"/>
25
+ <img src="https://img.shields.io/badge/version-v0.2.42-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"/>
@@ -180,6 +180,13 @@ echo "explain this diff" | git diff | dulus -p --accept-all
180
180
 
181
181
  <p align="center"><sub>↑ session boot. soul loaded, gold memory warm, shell sniffed. the little circles are real buttons on your Mac.</sub></p>
182
182
 
183
+ ### 💻 Dulus OS (Sandbox)
184
+ > [!NOTE]
185
+ > **Experimental features:** The folder `sandbox/` contains the early implementation of **Dulus OS** — a mini-operating system that runs entirely in your browser. It is currently in heavy development and not 100% functional yet. It will serve as a secure, isolated environment for browser-based tool execution and visualizations.
186
+
187
+ ---
188
+
189
+
183
190
  ---
184
191
 
185
192
  <p align="center"><img src="https://raw.githubusercontent.com/KevRojo/Dulus/main/docs/sec-features.svg" alt="Features" width="100%"></p>
@@ -3,7 +3,7 @@ import json
3
3
 
4
4
  # ── Import slash completer helpers ──
5
5
  try:
6
- from backend.ui.input import (
6
+ from ui.input import (
7
7
  setup as _setup_slash_complete,
8
8
  read_line as _read_line_pt,
9
9
  reset_session as _reset_pt_session,
@@ -9,22 +9,52 @@
9
9
  "project": {
10
10
  "name": "Dulus Command Center",
11
11
  "repo_stats": {
12
- "files": 241,
13
- "lines": 110197,
12
+ "files": 26697,
13
+ "lines": 3602498,
14
14
  "languages": {
15
15
  ".example": 5,
16
- ".py": 58599,
17
- ".html": 14582,
18
- "no_ext": 1158,
16
+ "no_ext": 16410,
17
+ ".py": 60171,
18
+ ".html": 15960,
19
19
  ".in": 2,
20
20
  ".toml": 123,
21
- ".md": 2050,
22
- ".txt": 40,
23
- ".TAG": 4,
24
- ".json": 728,
25
- ".svg": 1123,
26
- ".png": 31639,
27
- ".sh": 144
21
+ ".md": 79646,
22
+ ".txt": 1018,
23
+ ".json": 133634,
24
+ ".whl": 17908,
25
+ ".gz": 18064,
26
+ ".svg": 1168,
27
+ ".png": 157513,
28
+ ".sh": 144,
29
+ ".js": 1992568,
30
+ ".ts": 570599,
31
+ ".log": 1,
32
+ ".jpg": 1076,
33
+ ".tsx": 34508,
34
+ ".css": 2848,
35
+ ".cmd": 476,
36
+ ".ps1": 784,
37
+ ".tsbuildinfo": 2,
38
+ ".mts": 29541,
39
+ ".yml": 250,
40
+ ".markdown": 763,
41
+ ".flow": 21999,
42
+ ".cjs": 150052,
43
+ ".cts": 44618,
44
+ ".map": 5059,
45
+ ".mjs": 102525,
46
+ ".BSD": 59,
47
+ ".lock": 2598,
48
+ ".nix": 20,
49
+ ".bnf": 32,
50
+ ".coffee": 1,
51
+ ".1": 164,
52
+ ".php": 156,
53
+ ".jst": 1840,
54
+ ".def": 534,
55
+ ".node": 34828,
56
+ ".snap": 4138,
57
+ ".exe": 98693
28
58
  }
29
59
  },
30
60
  "recent_commits": [],
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dulus
3
- Version: 0.2.41
3
+ Version: 0.2.42
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.30-ff6b1f?style=flat-square&labelColor=07070a" alt="version"/>
72
+ <img src="https://img.shields.io/badge/version-v0.2.42-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"/>
@@ -227,6 +227,13 @@ echo "explain this diff" | git diff | dulus -p --accept-all
227
227
 
228
228
  <p align="center"><sub>↑ session boot. soul loaded, gold memory warm, shell sniffed. the little circles are real buttons on your Mac.</sub></p>
229
229
 
230
+ ### 💻 Dulus OS (Sandbox)
231
+ > [!NOTE]
232
+ > **Experimental features:** The folder `sandbox/` contains the early implementation of **Dulus OS** — a mini-operating system that runs entirely in your browser. It is currently in heavy development and not 100% functional yet. It will serve as a secure, isolated environment for browser-based tool execution and visualizations.
233
+
234
+ ---
235
+
236
+
230
237
  ---
231
238
 
232
239
  <p align="center"><img src="https://raw.githubusercontent.com/KevRojo/Dulus/main/docs/sec-features.svg" alt="Features" width="100%"></p>
@@ -115,6 +115,8 @@ Slash commands in REPL:
115
115
  /kimi_chats List recent Kimi conversations
116
116
  /webchat [port] Spawn web chat UI (background Flask server)
117
117
  /webchat stop Kill the webchat server
118
+ /sandbox Open Dulus Sandbox OS in browser (starts webchat if needed)
119
+ /sandbox stop Stop the webchat server
118
120
  /rtk [on|off] Toggle RTK token-optimized shell command rewriting
119
121
  /exit /quit Exit
120
122
  """
@@ -1828,6 +1830,46 @@ def cmd_webchat(args: str, state, config) -> bool:
1828
1830
  info(f"WebChat spawn timed out -- try opening {local_url} manually or check :{port}")
1829
1831
  return True
1830
1832
 
1833
+
1834
+ def cmd_sandbox(args: str, state, config) -> bool:
1835
+ """Open the Dulus Sandbox OS in the browser.
1836
+
1837
+ /sandbox — Ensure webchat is running, open /sandbox in browser
1838
+ /sandbox stop — Alias for /webchat stop
1839
+ """
1840
+ import webbrowser, time, urllib.request
1841
+
1842
+ arg = (args or "").strip().lower()
1843
+
1844
+ if arg in ("stop", "kill", "off"):
1845
+ return cmd_webchat("stop", state, config)
1846
+
1847
+ # Make sure webchat is running first
1848
+ import webchat_server
1849
+ port = config.get("_webchat_port", 5000)
1850
+
1851
+ def _wc_alive(p):
1852
+ try:
1853
+ urllib.request.urlopen(f"http://127.0.0.1:{p}/api/health", timeout=0.5).read(1)
1854
+ return True
1855
+ except Exception:
1856
+ return False
1857
+
1858
+ if not _wc_alive(port):
1859
+ ok("Starting WebChat first...")
1860
+ cmd_webchat("", state, config)
1861
+ # Wait up to 5s for it to be ready
1862
+ for _ in range(20):
1863
+ if _wc_alive(port):
1864
+ break
1865
+ time.sleep(0.25)
1866
+
1867
+ sandbox_url = f"http://127.0.0.1:{port}/sandbox"
1868
+ ok(f"Opening Sandbox OS -> {sandbox_url}")
1869
+ webbrowser.open(sandbox_url)
1870
+ info("Mini OS running in your browser. Use /sandbox stop to shut down the server.")
1871
+ return True
1872
+
1831
1873
  def cmd_gui(_args: str, _state, config) -> bool:
1832
1874
  """Launch the desktop GUI from the REPL."""
1833
1875
  try:
@@ -7440,6 +7482,7 @@ COMMANDS = {
7440
7482
  "voice": cmd_voice,
7441
7483
  "git": cmd_git,
7442
7484
  "webchat": cmd_webchat,
7485
+ "sandbox": cmd_sandbox,
7443
7486
  "gui": cmd_gui,
7444
7487
  "brave": cmd_brave,
7445
7488
  "rtk": cmd_rtk,
@@ -7579,7 +7622,8 @@ _CMD_META: dict[str, tuple[str, list[str]]] = {
7579
7622
  "gemini_chats": ("Manage Gemini Web conversations", ["new"]),
7580
7623
  "gemini_harvest": ("Harvest Gemini Web cookies (alias)", []),
7581
7624
  "harvest-claude": ("Harvest Claude.ai cookies (alias)", []),
7582
- "webchat": ("Spawn web chat UI", ["stop"]),
7625
+ "webchat": ("Spawn web chat UI", ["stop", "lan"]),
7626
+ "sandbox": ("Open Dulus Sandbox OS in browser", ["stop"]),
7583
7627
  "gui": ("Launch desktop GUI", []),
7584
7628
  }
7585
7629
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "dulus"
7
- version = "0.2.41"
7
+ version = "0.2.42"
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"
@@ -61,15 +61,25 @@ def _next_id() -> str:
61
61
  def create_task(
62
62
  subject: str,
63
63
  description: str,
64
+ status: str = "pending",
65
+ owner: str = "",
64
66
  active_form: str = "",
65
67
  metadata: dict[str, Any] | None = None,
66
68
  ) -> Task:
67
69
  with _lock:
68
70
  _load()
71
+ # Validate status enum
72
+ try:
73
+ task_status = TaskStatus(status)
74
+ except ValueError:
75
+ task_status = TaskStatus.PENDING
76
+
69
77
  task = Task(
70
78
  id=_next_id(),
71
79
  subject=subject,
72
80
  description=description,
81
+ status=task_status,
82
+ owner=owner,
73
83
  active_form=active_form,
74
84
  metadata=metadata or {},
75
85
  )
@@ -26,6 +26,15 @@ _TASK_CREATE_SCHEMA = {
26
26
  "type": "string",
27
27
  "description": "What needs to be done",
28
28
  },
29
+ "status": {
30
+ "type": "string",
31
+ "enum": ["pending", "in_progress", "completed", "cancelled"],
32
+ "description": "Current state of the task (default is 'pending')",
33
+ },
34
+ "owner": {
35
+ "type": "string",
36
+ "description": "The agent or user responsible (e.g. 'A', 'B', 'User')",
37
+ },
29
38
  "active_form": {
30
39
  "type": "string",
31
40
  "description": (
@@ -38,7 +47,7 @@ _TASK_CREATE_SCHEMA = {
38
47
  "description": "Arbitrary key-value metadata to attach to the task",
39
48
  },
40
49
  },
41
- "required": ["subject", "description"],
50
+ "required": ["subject", "description", "status", "owner"],
42
51
  },
43
52
  }
44
53
 
@@ -128,9 +137,9 @@ _TASK_LIST_SCHEMA = {
128
137
 
129
138
  # ── Implementations ────────────────────────────────────────────────────────────
130
139
 
131
- def _task_create(subject: str, description: str, active_form: str = "", metadata: dict = None) -> str:
132
- task = create_task(subject, description, active_form=active_form, metadata=metadata)
133
- return f"Task #{task.id} created: {task.subject}"
140
+ def _task_create(subject: str, description: str, status: str = "pending", owner: str = "", active_form: str = "", metadata: dict = None) -> str:
141
+ task = create_task(subject, description, status=status, owner=owner, active_form=active_form, metadata=metadata)
142
+ return f"Task #{task.id} created: {task.subject} (Owner: {task.owner}, Status: {task.status.value})"
134
143
 
135
144
 
136
145
  def _task_update(
@@ -220,8 +229,10 @@ def _register() -> None:
220
229
  func=lambda p, c: _task_create(
221
230
  p["subject"],
222
231
  p["description"],
223
- p.get("active_form", ""),
224
- p.get("metadata"),
232
+ status=p.get("status", "pending"),
233
+ owner=p.get("owner", ""),
234
+ active_form=p.get("active_form", ""),
235
+ metadata=p.get("metadata"),
225
236
  ),
226
237
  read_only=False,
227
238
  concurrent_safe=True,
@@ -59,7 +59,20 @@ def _is_in_tg_turn(config: dict) -> bool:
59
59
 
60
60
  # ── Tool JSON schemas (sent to Claude API) ─────────────────────────────────
61
61
 
62
+ _LAUNCH_SANDBOX_SCHEMA = {
63
+ "name": "LaunchSandbox",
64
+ "description": "Start the Dulus Sandbox (mini-OS) web interface in the browser. "
65
+ "Provides a visual desktop experience with integrated Dulus Terminal.",
66
+ "input_schema": {
67
+ "type": "object",
68
+ "properties": {
69
+ "stop": {"type": "boolean", "description": "If true, stop the server instead of starting it."}
70
+ },
71
+ },
72
+ }
73
+
62
74
  TOOL_SCHEMAS = [
75
+ _LAUNCH_SANDBOX_SCHEMA,
63
76
  {
64
77
  "name": "Read",
65
78
  "description": (
@@ -2683,6 +2696,30 @@ register_tool(ToolDef(name="GitStatus", schema=_GIT_STATUS_SCHEMA, func=_git_sta
2683
2696
  register_tool(ToolDef(name="GitLog", schema=_GIT_LOG_SCHEMA, func=_git_log, read_only=True, concurrent_safe=True))
2684
2697
 
2685
2698
 
2699
+ def _launch_sandbox(params: dict, config: dict) -> str:
2700
+ # Use the existing command handler from dulus.py
2701
+ try:
2702
+ from dulus import COMMANDS
2703
+ handler = COMMANDS.get("sandbox")
2704
+ if not handler:
2705
+ return "Error: /sandbox command not found in Dulus."
2706
+
2707
+ stop = params.get("stop", False)
2708
+ args = "stop" if stop else ""
2709
+
2710
+ state = config.get("_state")
2711
+ if not state:
2712
+ return "Error: Dulus session state not available to tool."
2713
+
2714
+ handler(args, state, config)
2715
+ return "Dulus Sandbox OS opened in browser." if not stop else "Sandbox stopped."
2716
+ except Exception as e:
2717
+ return f"Error launching sandbox: {e}"
2718
+
2719
+
2720
+ register_tool(ToolDef(name="LaunchSandbox", schema=_LAUNCH_SANDBOX_SCHEMA, func=_launch_sandbox))
2721
+
2722
+
2686
2723
  # Plugins are loaded once when Dulus starts (not on every reload to avoid overhead)
2687
2724
  try:
2688
2725
  from plugin.loader import register_plugin_tools
@@ -2700,3 +2737,5 @@ except Exception:
2700
2737
  # If plugin system fails, continue with core tools only
2701
2738
  _plugin_count = 0
2702
2739
 
2740
+
2741
+