dulus 3.7.0__tar.gz → 3.7.1__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 (333) hide show
  1. {dulus-3.7.0/dulus.egg-info → dulus-3.7.1}/PKG-INFO +1 -1
  2. {dulus-3.7.0 → dulus-3.7.1}/analytics.py +164 -164
  3. {dulus-3.7.0 → dulus-3.7.1/dulus.egg-info}/PKG-INFO +1 -1
  4. {dulus-3.7.0 → dulus-3.7.1}/dulus.egg-info/SOURCES.txt +2 -2
  5. {dulus-3.7.0 → dulus-3.7.1}/dulus_gui_web.py +825 -825
  6. dulus-3.7.1/dulus_tools/tree_ls.py +156 -0
  7. {dulus-3.7.0 → dulus-3.7.1}/gui/dulus_orchestrator/App.tsx +196 -196
  8. {dulus-3.7.0 → dulus-3.7.1}/gui/dulus_orchestrator/THIRD_PARTY_NOTICES.md +10 -10
  9. {dulus-3.7.0 → dulus-3.7.1}/gui/dulus_orchestrator/dist/index.html +188 -188
  10. {dulus-3.7.0 → dulus-3.7.1}/gui/dulus_orchestrator/dist/standalone.html +188 -188
  11. {dulus-3.7.0 → dulus-3.7.1}/gui/dulus_orchestrator/index.html +120 -120
  12. {dulus-3.7.0 → dulus-3.7.1}/gui/dulus_orchestrator/index.tsx +16 -16
  13. {dulus-3.7.0 → dulus-3.7.1}/gui/dulus_orchestrator/metadata.json +6 -6
  14. {dulus-3.7.0 → dulus-3.7.1}/gui/dulus_orchestrator/package-lock.json +3143 -3143
  15. {dulus-3.7.0 → dulus-3.7.1}/gui/dulus_orchestrator/package.json +30 -30
  16. {dulus-3.7.0 → dulus-3.7.1}/gui/dulus_orchestrator/types.ts +169 -169
  17. {dulus-3.7.0 → dulus-3.7.1}/gui/dulus_orchestrator/utils.ts +74 -74
  18. {dulus-3.7.0 → dulus-3.7.1}/gui/dulus_orchestrator/vertex-ai-proxy-interceptor.js +154 -154
  19. {dulus-3.7.0 → dulus-3.7.1}/gui/dulus_orchestrator/vite.config.ts +44 -44
  20. {dulus-3.7.0 → dulus-3.7.1}/pyproject.toml +1 -1
  21. dulus-3.7.0/tests/test_fs_compass.py → dulus-3.7.1/tests/test_tree_ls.py +86 -78
  22. {dulus-3.7.0 → dulus-3.7.1}/tools.py +3 -3
  23. dulus-3.7.0/dulus_tools/fs_compass.py +0 -472
  24. {dulus-3.7.0 → dulus-3.7.1}/LICENSE +0 -0
  25. {dulus-3.7.0 → dulus-3.7.1}/MANIFEST.in +0 -0
  26. {dulus-3.7.0 → dulus-3.7.1}/README.md +0 -0
  27. {dulus-3.7.0 → dulus-3.7.1}/agent.py +0 -0
  28. {dulus-3.7.0 → dulus-3.7.1}/backend/__init__.py +0 -0
  29. {dulus-3.7.0 → dulus-3.7.1}/backend/agents_bridge.py +0 -0
  30. {dulus-3.7.0 → dulus-3.7.1}/backend/compressor.py +0 -0
  31. {dulus-3.7.0 → dulus-3.7.1}/backend/context.py +0 -0
  32. {dulus-3.7.0 → dulus-3.7.1}/backend/githook.py +0 -0
  33. {dulus-3.7.0 → dulus-3.7.1}/backend/marketplace.py +0 -0
  34. {dulus-3.7.0 → dulus-3.7.1}/backend/mempalace_bridge.py +0 -0
  35. {dulus-3.7.0 → dulus-3.7.1}/backend/personas.py +0 -0
  36. {dulus-3.7.0 → dulus-3.7.1}/backend/plugins.py +0 -0
  37. {dulus-3.7.0 → dulus-3.7.1}/backend/server.py +0 -0
  38. {dulus-3.7.0 → dulus-3.7.1}/backend/tasks.py +0 -0
  39. {dulus-3.7.0 → dulus-3.7.1}/batch_api.py +0 -0
  40. {dulus-3.7.0 → dulus-3.7.1}/checkpoint/__init__.py +0 -0
  41. {dulus-3.7.0 → dulus-3.7.1}/checkpoint/hooks.py +0 -0
  42. {dulus-3.7.0 → dulus-3.7.1}/checkpoint/store.py +0 -0
  43. {dulus-3.7.0 → dulus-3.7.1}/checkpoint/types.py +0 -0
  44. {dulus-3.7.0 → dulus-3.7.1}/claude_code_watcher.py +0 -0
  45. {dulus-3.7.0 → dulus-3.7.1}/clipboard_utils.py +0 -0
  46. {dulus-3.7.0 → dulus-3.7.1}/cloudsave.py +0 -0
  47. {dulus-3.7.0 → dulus-3.7.1}/common.py +0 -0
  48. {dulus-3.7.0 → dulus-3.7.1}/compaction.py +0 -0
  49. {dulus-3.7.0 → dulus-3.7.1}/config.py +0 -0
  50. {dulus-3.7.0 → dulus-3.7.1}/context.py +0 -0
  51. {dulus-3.7.0 → dulus-3.7.1}/data/__init__.py +0 -0
  52. {dulus-3.7.0 → dulus-3.7.1}/data/active_persona.json +0 -0
  53. {dulus-3.7.0 → dulus-3.7.1}/data/marketplace.json +0 -0
  54. {dulus-3.7.0 → dulus-3.7.1}/data/personas.json +0 -0
  55. {dulus-3.7.0 → dulus-3.7.1}/data/plugins/__init__.py +0 -0
  56. {dulus-3.7.0 → dulus-3.7.1}/data/plugins/composio/__init__.py +0 -0
  57. {dulus-3.7.0 → dulus-3.7.1}/data/plugins/composio/composio_plugin/__init__.py +0 -0
  58. {dulus-3.7.0 → dulus-3.7.1}/data/plugins/composio/composio_plugin/session_manager.py +0 -0
  59. {dulus-3.7.0 → dulus-3.7.1}/data/plugins/composio/composio_plugin/tool_generator.py +0 -0
  60. {dulus-3.7.0 → dulus-3.7.1}/data/plugins/composio/plugin.json +0 -0
  61. {dulus-3.7.0 → dulus-3.7.1}/data/plugins/composio/plugin_tool.py +0 -0
  62. {dulus-3.7.0 → dulus-3.7.1}/data/tasks.json +0 -0
  63. {dulus-3.7.0 → dulus-3.7.1}/docs/API.md +0 -0
  64. {dulus-3.7.0 → dulus-3.7.1}/docs/BRAND_GUIDE.md +0 -0
  65. {dulus-3.7.0 → dulus-3.7.1}/docs/CHANGELOG.md +0 -0
  66. {dulus-3.7.0 → dulus-3.7.1}/docs/CONTRIBUTING.md +0 -0
  67. {dulus-3.7.0 → dulus-3.7.1}/docs/DEPLOYMENT.md +0 -0
  68. {dulus-3.7.0 → dulus-3.7.1}/docs/Dulus_AI_Whitepaper_(v2.0).pdf +0 -0
  69. {dulus-3.7.0 → dulus-3.7.1}/docs/FAQ.md +0 -0
  70. {dulus-3.7.0 → dulus-3.7.1}/docs/GETTING_STARTED.md +0 -0
  71. {dulus-3.7.0 → dulus-3.7.1}/docs/INVESTOR_BRIEF.md +0 -0
  72. {dulus-3.7.0 → dulus-3.7.1}/docs/README.md +0 -0
  73. {dulus-3.7.0 → dulus-3.7.1}/docs/README_AR.md +0 -0
  74. {dulus-3.7.0 → dulus-3.7.1}/docs/README_EN.md +0 -0
  75. {dulus-3.7.0 → dulus-3.7.1}/docs/README_ES.md +0 -0
  76. {dulus-3.7.0 → dulus-3.7.1}/docs/README_FR.md +0 -0
  77. {dulus-3.7.0 → dulus-3.7.1}/docs/README_JA.md +0 -0
  78. {dulus-3.7.0 → dulus-3.7.1}/docs/README_KO.md +0 -0
  79. {dulus-3.7.0 → dulus-3.7.1}/docs/README_PT.md +0 -0
  80. {dulus-3.7.0 → dulus-3.7.1}/docs/README_RU.md +0 -0
  81. {dulus-3.7.0 → dulus-3.7.1}/docs/README_ZH.md +0 -0
  82. {dulus-3.7.0 → dulus-3.7.1}/docs/SECURITY.md +0 -0
  83. {dulus-3.7.0 → dulus-3.7.1}/docs/__init__.py +0 -0
  84. {dulus-3.7.0 → dulus-3.7.1}/docs/api.html +0 -0
  85. {dulus-3.7.0 → dulus-3.7.1}/docs/architecture.md +0 -0
  86. {dulus-3.7.0 → dulus-3.7.1}/docs/azure-speech-template.json +0 -0
  87. {dulus-3.7.0 → dulus-3.7.1}/docs/dashboard/index.html +0 -0
  88. {dulus-3.7.0 → dulus-3.7.1}/docs/divider.svg +0 -0
  89. {dulus-3.7.0 → dulus-3.7.1}/docs/dulus-bird.png +0 -0
  90. {dulus-3.7.0 → dulus-3.7.1}/docs/generate.py +0 -0
  91. {dulus-3.7.0 → dulus-3.7.1}/docs/hero.svg +0 -0
  92. {dulus-3.7.0 → dulus-3.7.1}/docs/index.html +0 -0
  93. {dulus-3.7.0 → dulus-3.7.1}/docs/news.md +0 -0
  94. {dulus-3.7.0 → dulus-3.7.1}/docs/nvidia-models.svg +0 -0
  95. {dulus-3.7.0 → dulus-3.7.1}/docs/particle-playground.html +0 -0
  96. {dulus-3.7.0 → dulus-3.7.1}/docs/personas/index.html +0 -0
  97. {dulus-3.7.0 → dulus-3.7.1}/docs/poetry-banner.png +0 -0
  98. {dulus-3.7.0 → dulus-3.7.1}/docs/preview.html +0 -0
  99. {dulus-3.7.0 → dulus-3.7.1}/docs/sec-agents.svg +0 -0
  100. {dulus-3.7.0 → dulus-3.7.1}/docs/sec-brainstorm.svg +0 -0
  101. {dulus-3.7.0 → dulus-3.7.1}/docs/sec-bridges.svg +0 -0
  102. {dulus-3.7.0 → dulus-3.7.1}/docs/sec-features.svg +0 -0
  103. {dulus-3.7.0 → dulus-3.7.1}/docs/sec-freetier.svg +0 -0
  104. {dulus-3.7.0 → dulus-3.7.1}/docs/sec-memory.svg +0 -0
  105. {dulus-3.7.0 → dulus-3.7.1}/docs/sec-models.svg +0 -0
  106. {dulus-3.7.0 → dulus-3.7.1}/docs/sec-perms.svg +0 -0
  107. {dulus-3.7.0 → dulus-3.7.1}/docs/sec-plugins.svg +0 -0
  108. {dulus-3.7.0 → dulus-3.7.1}/docs/sec-quickstart.svg +0 -0
  109. {dulus-3.7.0 → dulus-3.7.1}/docs/sec-ssj.svg +0 -0
  110. {dulus-3.7.0 → dulus-3.7.1}/docs/spinners.svg +0 -0
  111. {dulus-3.7.0 → dulus-3.7.1}/docs/split-pane.svg +0 -0
  112. {dulus-3.7.0 → dulus-3.7.1}/docs/terminal-boot.svg +0 -0
  113. {dulus-3.7.0 → dulus-3.7.1}/dulus.egg-info/dependency_links.txt +0 -0
  114. {dulus-3.7.0 → dulus-3.7.1}/dulus.egg-info/entry_points.txt +0 -0
  115. {dulus-3.7.0 → dulus-3.7.1}/dulus.egg-info/requires.txt +0 -0
  116. {dulus-3.7.0 → dulus-3.7.1}/dulus.egg-info/top_level.txt +0 -0
  117. {dulus-3.7.0 → dulus-3.7.1}/dulus.py +0 -0
  118. {dulus-3.7.0 → dulus-3.7.1}/dulus_gui.py +0 -0
  119. {dulus-3.7.0 → dulus-3.7.1}/dulus_mcp/__init__.py +0 -0
  120. {dulus-3.7.0 → dulus-3.7.1}/dulus_mcp/client.py +0 -0
  121. {dulus-3.7.0 → dulus-3.7.1}/dulus_mcp/config.py +0 -0
  122. {dulus-3.7.0 → dulus-3.7.1}/dulus_mcp/tools.py +0 -0
  123. {dulus-3.7.0 → dulus-3.7.1}/dulus_mcp/types.py +0 -0
  124. {dulus-3.7.0 → dulus-3.7.1}/dulus_tools/__init__.py +0 -0
  125. {dulus-3.7.0 → dulus-3.7.1}/dulus_tools/add_dir_manager.py +0 -0
  126. {dulus-3.7.0 → dulus-3.7.1}/dulus_tools/afk_mode.py +0 -0
  127. {dulus-3.7.0 → dulus-3.7.1}/dulus_tools/approval_runtime.py +0 -0
  128. {dulus-3.7.0 → dulus-3.7.1}/dulus_tools/background_tasks.py +0 -0
  129. {dulus-3.7.0 → dulus-3.7.1}/dulus_tools/clipboard_utils.py +0 -0
  130. {dulus-3.7.0 → dulus-3.7.1}/dulus_tools/diff_visualizer.py +0 -0
  131. {dulus-3.7.0 → dulus-3.7.1}/dulus_tools/export_import.py +0 -0
  132. {dulus-3.7.0 → dulus-3.7.1}/dulus_tools/hook_engine.py +0 -0
  133. {dulus-3.7.0 → dulus-3.7.1}/dulus_tools/notification_manager.py +0 -0
  134. {dulus-3.7.0 → dulus-3.7.1}/dulus_tools/session_fork.py +0 -0
  135. {dulus-3.7.0 → dulus-3.7.1}/dulus_tools/shell_mode.py +0 -0
  136. {dulus-3.7.0 → dulus-3.7.1}/dulus_tools/todo_visualizer.py +0 -0
  137. {dulus-3.7.0 → dulus-3.7.1}/dulus_tools/wire_events.py +0 -0
  138. {dulus-3.7.0 → dulus-3.7.1}/dulus_tools/yolo_mode.py +0 -0
  139. {dulus-3.7.0 → dulus-3.7.1}/governance.py +0 -0
  140. {dulus-3.7.0 → dulus-3.7.1}/gui/__init__.py +0 -0
  141. {dulus-3.7.0 → dulus-3.7.1}/gui/agent_bridge.py +0 -0
  142. {dulus-3.7.0 → dulus-3.7.1}/gui/chat_widget.py +0 -0
  143. {dulus-3.7.0 → dulus-3.7.1}/gui/main_window.py +0 -0
  144. {dulus-3.7.0 → dulus-3.7.1}/gui/personas.py +0 -0
  145. {dulus-3.7.0 → dulus-3.7.1}/gui/sandbox_server.py +0 -0
  146. {dulus-3.7.0 → dulus-3.7.1}/gui/session_utils.py +0 -0
  147. {dulus-3.7.0 → dulus-3.7.1}/gui/settings_dialog.py +0 -0
  148. {dulus-3.7.0 → dulus-3.7.1}/gui/sidebar.py +0 -0
  149. {dulus-3.7.0 → dulus-3.7.1}/gui/tasks_view.py +0 -0
  150. {dulus-3.7.0 → dulus-3.7.1}/gui/themes.py +0 -0
  151. {dulus-3.7.0 → dulus-3.7.1}/gui/tool_panel.py +0 -0
  152. {dulus-3.7.0 → dulus-3.7.1}/input.py +0 -0
  153. {dulus-3.7.0 → dulus-3.7.1}/license_manager.py +0 -0
  154. {dulus-3.7.0 → dulus-3.7.1}/memory/__init__.py +0 -0
  155. {dulus-3.7.0 → dulus-3.7.1}/memory/audit.py +0 -0
  156. {dulus-3.7.0 → dulus-3.7.1}/memory/consolidator.py +0 -0
  157. {dulus-3.7.0 → dulus-3.7.1}/memory/context.py +0 -0
  158. {dulus-3.7.0 → dulus-3.7.1}/memory/offload.py +0 -0
  159. {dulus-3.7.0 → dulus-3.7.1}/memory/palace.py +0 -0
  160. {dulus-3.7.0 → dulus-3.7.1}/memory/scan.py +0 -0
  161. {dulus-3.7.0 → dulus-3.7.1}/memory/sessions.py +0 -0
  162. {dulus-3.7.0 → dulus-3.7.1}/memory/store.py +0 -0
  163. {dulus-3.7.0 → dulus-3.7.1}/memory/tools.py +0 -0
  164. {dulus-3.7.0 → dulus-3.7.1}/memory/types.py +0 -0
  165. {dulus-3.7.0 → dulus-3.7.1}/memory/vector_search.py +0 -0
  166. {dulus-3.7.0 → dulus-3.7.1}/multi_agent/__init__.py +0 -0
  167. {dulus-3.7.0 → dulus-3.7.1}/multi_agent/subagent.py +0 -0
  168. {dulus-3.7.0 → dulus-3.7.1}/multi_agent/tools.py +0 -0
  169. {dulus-3.7.0 → dulus-3.7.1}/offload_helper.py +0 -0
  170. {dulus-3.7.0 → dulus-3.7.1}/personality_config.py +0 -0
  171. {dulus-3.7.0 → dulus-3.7.1}/plugin/__init__.py +0 -0
  172. {dulus-3.7.0 → dulus-3.7.1}/plugin/autoadapter.py +0 -0
  173. {dulus-3.7.0 → dulus-3.7.1}/plugin/loader.py +0 -0
  174. {dulus-3.7.0 → dulus-3.7.1}/plugin/recommend.py +0 -0
  175. {dulus-3.7.0 → dulus-3.7.1}/plugin/store.py +0 -0
  176. {dulus-3.7.0 → dulus-3.7.1}/plugin/types.py +0 -0
  177. {dulus-3.7.0 → dulus-3.7.1}/providers.py +0 -0
  178. {dulus-3.7.0 → dulus-3.7.1}/sandbox/README.md +0 -0
  179. {dulus-3.7.0 → dulus-3.7.1}/sandbox/__init__.py +0 -0
  180. {dulus-3.7.0 → dulus-3.7.1}/sandbox/components.json +0 -0
  181. {dulus-3.7.0 → dulus-3.7.1}/sandbox/dist/assets/index-DE51D6wI.css +0 -0
  182. {dulus-3.7.0 → dulus-3.7.1}/sandbox/dist/assets/index-DMCCNE9Y.js +0 -0
  183. {dulus-3.7.0 → dulus-3.7.1}/sandbox/dist/index.html +0 -0
  184. {dulus-3.7.0 → dulus-3.7.1}/sandbox/dist/wallpaper-default.jpg +0 -0
  185. {dulus-3.7.0 → dulus-3.7.1}/sandbox/dist/wallpapers/default.jpeg +0 -0
  186. {dulus-3.7.0 → dulus-3.7.1}/sandbox/dist/wallpapers/light.jpeg +0 -0
  187. {dulus-3.7.0 → dulus-3.7.1}/sandbox/dist/wallpapers/nature.jpeg +0 -0
  188. {dulus-3.7.0 → dulus-3.7.1}/sandbox/dist/wallpapers/tech.jpeg +0 -0
  189. {dulus-3.7.0 → dulus-3.7.1}/sandbox/eslint.config.js +0 -0
  190. {dulus-3.7.0 → dulus-3.7.1}/sandbox/index.html +0 -0
  191. {dulus-3.7.0 → dulus-3.7.1}/sandbox/info.md +0 -0
  192. {dulus-3.7.0 → dulus-3.7.1}/sandbox/package-lock.json +0 -0
  193. {dulus-3.7.0 → dulus-3.7.1}/sandbox/package.json +0 -0
  194. {dulus-3.7.0 → dulus-3.7.1}/sandbox/postcss.config.js +0 -0
  195. {dulus-3.7.0 → dulus-3.7.1}/sandbox/tailwind.config.js +0 -0
  196. {dulus-3.7.0 → dulus-3.7.1}/sandbox/tsconfig.app.json +0 -0
  197. {dulus-3.7.0 → dulus-3.7.1}/sandbox/tsconfig.json +0 -0
  198. {dulus-3.7.0 → dulus-3.7.1}/sandbox/tsconfig.node.json +0 -0
  199. {dulus-3.7.0 → dulus-3.7.1}/sandbox/vite.config.ts +0 -0
  200. {dulus-3.7.0 → dulus-3.7.1}/sandbox_bootstrap.py +0 -0
  201. {dulus-3.7.0 → dulus-3.7.1}/setup.cfg +0 -0
  202. {dulus-3.7.0 → dulus-3.7.1}/skill/__init__.py +0 -0
  203. {dulus-3.7.0 → dulus-3.7.1}/skill/builtin.py +0 -0
  204. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/LICENSE-obsidian-skills +0 -0
  205. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/README.md +0 -0
  206. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/defuddle/SKILL.md +0 -0
  207. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/json-canvas/SKILL.md +0 -0
  208. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/json-canvas/references/EXAMPLES.md +0 -0
  209. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/obsidian-bases/SKILL.md +0 -0
  210. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/obsidian-bases/references/FUNCTIONS_REFERENCE.md +0 -0
  211. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/obsidian-cli/SKILL.md +0 -0
  212. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/obsidian-markdown/SKILL.md +0 -0
  213. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/obsidian-markdown/references/CALLOUTS.md +0 -0
  214. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/obsidian-markdown/references/EMBEDS.md +0 -0
  215. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/obsidian-markdown/references/PROPERTIES.md +0 -0
  216. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/README.md +0 -0
  217. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/SKILL.md +0 -0
  218. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/references/brokers/addresses.json +0 -0
  219. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/references/brokers/advancedbackgroundchecks.json +0 -0
  220. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/references/brokers/beenverified.json +0 -0
  221. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/references/brokers/clustal.json +0 -0
  222. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/references/brokers/clustrmaps.json +0 -0
  223. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/references/brokers/cyberbackgroundchecks.json +0 -0
  224. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/references/brokers/familytreenow.json +0 -0
  225. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/references/brokers/fastpeoplesearch.json +0 -0
  226. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/references/brokers/intelius.json +0 -0
  227. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/references/brokers/mylife.json +0 -0
  228. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/references/brokers/nuwber.json +0 -0
  229. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/references/brokers/peekyou.json +0 -0
  230. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/references/brokers/peoplefinders.json +0 -0
  231. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/references/brokers/radaris.json +0 -0
  232. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/references/brokers/rehold.json +0 -0
  233. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/references/brokers/searchpeoplefree.json +0 -0
  234. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/references/brokers/socialcatfish.json +0 -0
  235. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/references/brokers/spokeo.json +0 -0
  236. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/references/brokers/thatsthem.json +0 -0
  237. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/references/brokers/truepeoplesearch.json +0 -0
  238. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/references/brokers/usphonebook.json +0 -0
  239. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/references/brokers/whitepages.json +0 -0
  240. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/references/legal/ccpa.md +0 -0
  241. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/references/legal/drop.md +0 -0
  242. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/references/legal/gdpr.md +0 -0
  243. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/references/methods.md +0 -0
  244. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/references/site-playbooks.md +0 -0
  245. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/references/state-machine.md +0 -0
  246. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/scripts/autopilot.py +0 -0
  247. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/scripts/badbool.py +0 -0
  248. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/scripts/brokers.py +0 -0
  249. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/scripts/cdp.py +0 -0
  250. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/scripts/config.py +0 -0
  251. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/scripts/crypto.py +0 -0
  252. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/scripts/dossier.py +0 -0
  253. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/scripts/email_modes.py +0 -0
  254. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/scripts/emailer.py +0 -0
  255. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/scripts/ledger.py +0 -0
  256. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/scripts/legal.py +0 -0
  257. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/scripts/paths.py +0 -0
  258. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/scripts/pdd.py +0 -0
  259. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/scripts/registry.py +0 -0
  260. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/scripts/report.py +0 -0
  261. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/scripts/scan.py +0 -0
  262. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/scripts/storage.py +0 -0
  263. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/scripts/tiers.py +0 -0
  264. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/scripts/vectors.py +0 -0
  265. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/templates/consent/authorization.md +0 -0
  266. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/templates/emails/ccpa-authorized-agent.txt +0 -0
  267. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/templates/emails/ccpa-deletion.txt +0 -0
  268. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/templates/emails/ccpa-indirect-deletion.txt +0 -0
  269. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/templates/emails/gdpr-erasure.txt +0 -0
  270. {dulus-3.7.0 → dulus-3.7.1}/skill/bundled/unbroker/templates/emails/generic-optout.txt +0 -0
  271. {dulus-3.7.0 → dulus-3.7.1}/skill/clawhub.py +0 -0
  272. {dulus-3.7.0 → dulus-3.7.1}/skill/executor.py +0 -0
  273. {dulus-3.7.0 → dulus-3.7.1}/skill/loader.py +0 -0
  274. {dulus-3.7.0 → dulus-3.7.1}/skill/tools.py +0 -0
  275. {dulus-3.7.0 → dulus-3.7.1}/skills.py +0 -0
  276. {dulus-3.7.0 → dulus-3.7.1}/soul.py +0 -0
  277. {dulus-3.7.0 → dulus-3.7.1}/spinner.py +0 -0
  278. {dulus-3.7.0 → dulus-3.7.1}/string_utils.py +0 -0
  279. {dulus-3.7.0 → dulus-3.7.1}/subagent.py +0 -0
  280. {dulus-3.7.0 → dulus-3.7.1}/task/__init__.py +0 -0
  281. {dulus-3.7.0 → dulus-3.7.1}/task/store.py +0 -0
  282. {dulus-3.7.0 → dulus-3.7.1}/task/tools.py +0 -0
  283. {dulus-3.7.0 → dulus-3.7.1}/task/types.py +0 -0
  284. {dulus-3.7.0 → dulus-3.7.1}/tests/test_afk_yolo.py +0 -0
  285. {dulus-3.7.0 → dulus-3.7.1}/tests/test_approval_runtime.py +0 -0
  286. {dulus-3.7.0 → dulus-3.7.1}/tests/test_background_task_tools.py +0 -0
  287. {dulus-3.7.0 → dulus-3.7.1}/tests/test_background_tasks.py +0 -0
  288. {dulus-3.7.0 → dulus-3.7.1}/tests/test_checkpoint.py +0 -0
  289. {dulus-3.7.0 → dulus-3.7.1}/tests/test_clipboard_utils.py +0 -0
  290. {dulus-3.7.0 → dulus-3.7.1}/tests/test_compaction.py +0 -0
  291. {dulus-3.7.0 → dulus-3.7.1}/tests/test_diff_view.py +0 -0
  292. {dulus-3.7.0 → dulus-3.7.1}/tests/test_diff_visualization.py +0 -0
  293. {dulus-3.7.0 → dulus-3.7.1}/tests/test_display_blocks.py +0 -0
  294. {dulus-3.7.0 → dulus-3.7.1}/tests/test_export_import.py +0 -0
  295. {dulus-3.7.0 → dulus-3.7.1}/tests/test_hook_engine.py +0 -0
  296. {dulus-3.7.0 → dulus-3.7.1}/tests/test_injection_fix.py +0 -0
  297. {dulus-3.7.0 → dulus-3.7.1}/tests/test_license.py +0 -0
  298. {dulus-3.7.0 → dulus-3.7.1}/tests/test_mcp.py +0 -0
  299. {dulus-3.7.0 → dulus-3.7.1}/tests/test_memory.py +0 -0
  300. {dulus-3.7.0 → dulus-3.7.1}/tests/test_notification_manager.py +0 -0
  301. {dulus-3.7.0 → dulus-3.7.1}/tests/test_plugin.py +0 -0
  302. {dulus-3.7.0 → dulus-3.7.1}/tests/test_session_fork.py +0 -0
  303. {dulus-3.7.0 → dulus-3.7.1}/tests/test_shell_mode.py +0 -0
  304. {dulus-3.7.0 → dulus-3.7.1}/tests/test_skills.py +0 -0
  305. {dulus-3.7.0 → dulus-3.7.1}/tests/test_steer_input.py +0 -0
  306. {dulus-3.7.0 → dulus-3.7.1}/tests/test_subagent.py +0 -0
  307. {dulus-3.7.0 → dulus-3.7.1}/tests/test_task.py +0 -0
  308. {dulus-3.7.0 → dulus-3.7.1}/tests/test_telegram_buffer.py +0 -0
  309. {dulus-3.7.0 → dulus-3.7.1}/tests/test_think_tool.py +0 -0
  310. {dulus-3.7.0 → dulus-3.7.1}/tests/test_todo_tool.py +0 -0
  311. {dulus-3.7.0 → dulus-3.7.1}/tests/test_todo_visualization.py +0 -0
  312. {dulus-3.7.0 → dulus-3.7.1}/tests/test_tool_registry.py +0 -0
  313. {dulus-3.7.0 → dulus-3.7.1}/tests/test_voice.py +0 -0
  314. {dulus-3.7.0 → dulus-3.7.1}/tests/test_wire_events.py +0 -0
  315. {dulus-3.7.0 → dulus-3.7.1}/tmux_offloader.py +0 -0
  316. {dulus-3.7.0 → dulus-3.7.1}/tmux_tools.py +0 -0
  317. {dulus-3.7.0 → dulus-3.7.1}/tool_registry.py +0 -0
  318. {dulus-3.7.0 → dulus-3.7.1}/ui/__init__.py +0 -0
  319. {dulus-3.7.0 → dulus-3.7.1}/ui/input.py +0 -0
  320. {dulus-3.7.0 → dulus-3.7.1}/ui/render.py +0 -0
  321. {dulus-3.7.0 → dulus-3.7.1}/voice/__init__.py +0 -0
  322. {dulus-3.7.0 → dulus-3.7.1}/voice/audio_utils.py +0 -0
  323. {dulus-3.7.0 → dulus-3.7.1}/voice/keyterms.py +0 -0
  324. {dulus-3.7.0 → dulus-3.7.1}/voice/recorder.py +0 -0
  325. {dulus-3.7.0 → dulus-3.7.1}/voice/stt.py +0 -0
  326. {dulus-3.7.0 → dulus-3.7.1}/voice/tts.py +0 -0
  327. {dulus-3.7.0 → dulus-3.7.1}/voice/wake_word.py +0 -0
  328. {dulus-3.7.0 → dulus-3.7.1}/webbridge/__init__.py +0 -0
  329. {dulus-3.7.0 → dulus-3.7.1}/webbridge/core.py +0 -0
  330. {dulus-3.7.0 → dulus-3.7.1}/webbridge/tools.py +0 -0
  331. {dulus-3.7.0 → dulus-3.7.1}/webchat.py +0 -0
  332. {dulus-3.7.0 → dulus-3.7.1}/webchat_server.py +0 -0
  333. {dulus-3.7.0 → dulus-3.7.1}/welcome.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dulus
3
- Version: 3.7.0
3
+ Version: 3.7.1
4
4
  Summary: Use IA as an agent without an API key. $0. Harvest your browser session for Gemini (guest, no login), Claude.ai, Claude Code, Kimi.com, Qwen, DeepSeek — drive them like an API, no per-token billing. Plus LiteLLM (100+ paid providers), local models via Ollama, /lang in 34 languages, Mesa Redonda, voice, OCR, MemPalace, embedded sandbox OS.
5
5
  Author: KevRojo
6
6
  License: GPL-3.0
@@ -1,164 +1,164 @@
1
- """Dulus anonymous usage telemetry (opt-in, privacy-first).
2
-
3
- Dulus asks ONCE on startup whether you want to share anonymous usage
4
- statistics. Nothing is sent until you explicitly say yes.
5
-
6
- What IS collected (when enabled):
7
- - Event names (session_start, message_sent, tool_used, model_selected)
8
- - Dulus version, OS name, Python version
9
- - Provider/model *names* (e.g. "gemini", "claude-sonnet")
10
- - A random anonymous ID (UUID generated locally — not tied to you)
11
-
12
- What is NEVER collected:
13
- - Prompts, responses, or any conversation content
14
- - File paths, file contents, or code
15
- - Usernames, emails, hostnames, IPs (Mixpanel geo is disabled via $ip=0)
16
- - API keys or tokens
17
-
18
- Where it goes: Mixpanel (https://mixpanel.com) — event analytics only.
19
-
20
- Opt out at any time (any of these):
21
- - Answer "n" at the first-run prompt
22
- - /config telemetry=off (inside Dulus)
23
- - DULUS_TELEMETRY=0 (environment variable)
24
-
25
- Implementation notes: zero third-party dependencies — plain urllib POST to
26
- the Mixpanel ingestion API in a fire-and-forget daemon thread. Failures are
27
- silently ignored; telemetry must never slow down or break Dulus.
28
- """
29
- from __future__ import annotations
30
-
31
- import base64
32
- import json
33
- import os
34
- import platform
35
- import sys
36
- import threading
37
- import time
38
- import uuid
39
-
40
- # Mixpanel PROJECT TOKEN for the public Dulus project.
41
- # NOTE: Mixpanel ingestion tokens are write-only and designed to ship in
42
- # client code (every website using Mixpanel exposes theirs). It cannot be
43
- # used to read any data. Override with DULUS_MP_TOKEN.
44
- MP_TOKEN = os.environ.get("DULUS_MP_TOKEN", "966ce8f5ccb32f06788f51be9f8bf8f5")
45
-
46
- _MP_ENDPOINT = "https://api.mixpanel.com/track"
47
-
48
- # Populated by init_telemetry(); None = not initialised / disabled.
49
- _distinct_id: str | None = None
50
- _enabled: bool = False
51
- _dulus_version: str = ""
52
-
53
-
54
- def _env_disabled() -> bool:
55
- return os.environ.get("DULUS_TELEMETRY", "").strip().lower() in ("0", "off", "false", "no")
56
-
57
-
58
- def is_enabled() -> bool:
59
- return _enabled and not _env_disabled() and bool(MP_TOKEN)
60
-
61
-
62
- CONSENT_NOTICE = """
63
- ── Ayuda a mejorar Dulus / Help improve Dulus ─────────────────────────
64
- Dulus can share ANONYMOUS usage statistics to help us understand
65
- which features matter (event counts only — sent to Mixpanel).
66
-
67
- Collected: event names, Dulus version, OS, model/provider names,
68
- a random anonymous ID generated on this machine.
69
- NEVER: prompts, responses, files, paths, keys, emails, IPs.
70
-
71
- Change your mind anytime: /config telemetry=off or DULUS_TELEMETRY=0
72
- ────────────────────────────────────────────────────────────────────────
73
- """
74
-
75
-
76
- def ask_consent(config: dict) -> dict:
77
- """One-time interactive consent prompt. Mutates + returns config.
78
-
79
- Only call when config['telemetry'] is unset and stdin is a TTY.
80
- """
81
- print(CONSENT_NOTICE)
82
- try:
83
- answer = input(" Share anonymous usage stats? [y/N] ").strip().lower()
84
- except (EOFError, KeyboardInterrupt):
85
- answer = ""
86
- config["telemetry"] = answer in ("y", "yes", "s", "si", "sí")
87
- if config["telemetry"] and not config.get("telemetry_id"):
88
- config["telemetry_id"] = uuid.uuid4().hex
89
- state = "enabled — thank you! 🦅" if config["telemetry"] else "disabled."
90
- print(f" Telemetry {state}\n")
91
- return config
92
-
93
-
94
- def init_telemetry(config: dict, version: str = "") -> None:
95
- """Initialise the module from config. Safe to call multiple times."""
96
- global _distinct_id, _enabled, _dulus_version
97
- _dulus_version = version or _dulus_version
98
- _enabled = bool(config.get("telemetry")) and not _env_disabled()
99
- if _enabled:
100
- _distinct_id = config.get("telemetry_id") or uuid.uuid4().hex
101
- config.setdefault("telemetry_id", _distinct_id)
102
-
103
-
104
- def track(event: str, properties: dict | None = None) -> None:
105
- """Fire-and-forget anonymous event. No-op unless telemetry is enabled."""
106
- if not is_enabled() or not _distinct_id:
107
- return
108
-
109
- payload = {
110
- "event": event,
111
- "properties": {
112
- "token": MP_TOKEN,
113
- "distinct_id": _distinct_id,
114
- "time": int(time.time()),
115
- "$ip": 0, # disable Mixpanel geolocation
116
- "dulus_version": _dulus_version,
117
- "os": platform.system(),
118
- "python": f"{sys.version_info.major}.{sys.version_info.minor}",
119
- **(properties or {}),
120
- },
121
- }
122
-
123
- def _send() -> None:
124
- try:
125
- from urllib.request import Request, urlopen
126
- from urllib.parse import urlencode
127
-
128
- data = urlencode(
129
- {"data": base64.b64encode(json.dumps([payload]).encode()).decode()}
130
- ).encode()
131
- req = Request(_MP_ENDPOINT, data=data, method="POST")
132
- urlopen(req, timeout=4).read()
133
- except Exception:
134
- pass # telemetry must never break Dulus
135
-
136
- threading.Thread(target=_send, daemon=True, name="telemetry").start()
137
-
138
-
139
- def track_session_start(config: dict) -> None:
140
- """Convenience: one event per REPL boot (enough for DAU/MAU counts)."""
141
- track("session_start", {
142
- "provider": str(config.get("provider", "")),
143
- "model": str(config.get("model", "")),
144
- })
145
-
146
-
147
- def track_message_sent(model: str = "") -> None:
148
- """One event per user prompt sent to the LLM (no content — count only)."""
149
- track("message_sent", {"model": model})
150
-
151
-
152
- def track_tool_used(tool_name: str) -> None:
153
- """One event per tool invocation (tool NAME only — never inputs)."""
154
- track("tool_used", {"tool": tool_name})
155
-
156
-
157
- def track_command_used(command: str) -> None:
158
- """One event per slash command (command NAME only — never args)."""
159
- track("command_used", {"command": command})
160
-
161
-
162
- def track_model_selected(model: str, provider: str = "") -> None:
163
- """Fired when the user switches models via /model."""
164
- track("model_selected", {"model": model, "provider": provider})
1
+ """Dulus anonymous usage telemetry (opt-in, privacy-first).
2
+
3
+ Dulus asks ONCE on startup whether you want to share anonymous usage
4
+ statistics. Nothing is sent until you explicitly say yes.
5
+
6
+ What IS collected (when enabled):
7
+ - Event names (session_start, message_sent, tool_used, model_selected)
8
+ - Dulus version, OS name, Python version
9
+ - Provider/model *names* (e.g. "gemini", "claude-sonnet")
10
+ - A random anonymous ID (UUID generated locally — not tied to you)
11
+
12
+ What is NEVER collected:
13
+ - Prompts, responses, or any conversation content
14
+ - File paths, file contents, or code
15
+ - Usernames, emails, hostnames, IPs (Mixpanel geo is disabled via $ip=0)
16
+ - API keys or tokens
17
+
18
+ Where it goes: Mixpanel (https://mixpanel.com) — event analytics only.
19
+
20
+ Opt out at any time (any of these):
21
+ - Answer "n" at the first-run prompt
22
+ - /config telemetry=off (inside Dulus)
23
+ - DULUS_TELEMETRY=0 (environment variable)
24
+
25
+ Implementation notes: zero third-party dependencies — plain urllib POST to
26
+ the Mixpanel ingestion API in a fire-and-forget daemon thread. Failures are
27
+ silently ignored; telemetry must never slow down or break Dulus.
28
+ """
29
+ from __future__ import annotations
30
+
31
+ import base64
32
+ import json
33
+ import os
34
+ import platform
35
+ import sys
36
+ import threading
37
+ import time
38
+ import uuid
39
+
40
+ # Mixpanel PROJECT TOKEN for the public Dulus project.
41
+ # NOTE: Mixpanel ingestion tokens are write-only and designed to ship in
42
+ # client code (every website using Mixpanel exposes theirs). It cannot be
43
+ # used to read any data. Override with DULUS_MP_TOKEN.
44
+ MP_TOKEN = os.environ.get("DULUS_MP_TOKEN", "966ce8f5ccb32f06788f51be9f8bf8f5")
45
+
46
+ _MP_ENDPOINT = "https://api.mixpanel.com/track"
47
+
48
+ # Populated by init_telemetry(); None = not initialised / disabled.
49
+ _distinct_id: str | None = None
50
+ _enabled: bool = False
51
+ _dulus_version: str = ""
52
+
53
+
54
+ def _env_disabled() -> bool:
55
+ return os.environ.get("DULUS_TELEMETRY", "").strip().lower() in ("0", "off", "false", "no")
56
+
57
+
58
+ def is_enabled() -> bool:
59
+ return _enabled and not _env_disabled() and bool(MP_TOKEN)
60
+
61
+
62
+ CONSENT_NOTICE = """
63
+ ── Ayuda a mejorar Dulus / Help improve Dulus ─────────────────────────
64
+ Dulus can share ANONYMOUS usage statistics to help us understand
65
+ which features matter (event counts only — sent to Mixpanel).
66
+
67
+ Collected: event names, Dulus version, OS, model/provider names,
68
+ a random anonymous ID generated on this machine.
69
+ NEVER: prompts, responses, files, paths, keys, emails, IPs.
70
+
71
+ Change your mind anytime: /config telemetry=off or DULUS_TELEMETRY=0
72
+ ────────────────────────────────────────────────────────────────────────
73
+ """
74
+
75
+
76
+ def ask_consent(config: dict) -> dict:
77
+ """One-time interactive consent prompt. Mutates + returns config.
78
+
79
+ Only call when config['telemetry'] is unset and stdin is a TTY.
80
+ """
81
+ print(CONSENT_NOTICE)
82
+ try:
83
+ answer = input(" Share anonymous usage stats? [y/N] ").strip().lower()
84
+ except (EOFError, KeyboardInterrupt):
85
+ answer = ""
86
+ config["telemetry"] = answer in ("y", "yes", "s", "si", "sí")
87
+ if config["telemetry"] and not config.get("telemetry_id"):
88
+ config["telemetry_id"] = uuid.uuid4().hex
89
+ state = "enabled — thank you! 🦅" if config["telemetry"] else "disabled."
90
+ print(f" Telemetry {state}\n")
91
+ return config
92
+
93
+
94
+ def init_telemetry(config: dict, version: str = "") -> None:
95
+ """Initialise the module from config. Safe to call multiple times."""
96
+ global _distinct_id, _enabled, _dulus_version
97
+ _dulus_version = version or _dulus_version
98
+ _enabled = bool(config.get("telemetry")) and not _env_disabled()
99
+ if _enabled:
100
+ _distinct_id = config.get("telemetry_id") or uuid.uuid4().hex
101
+ config.setdefault("telemetry_id", _distinct_id)
102
+
103
+
104
+ def track(event: str, properties: dict | None = None) -> None:
105
+ """Fire-and-forget anonymous event. No-op unless telemetry is enabled."""
106
+ if not is_enabled() or not _distinct_id:
107
+ return
108
+
109
+ payload = {
110
+ "event": event,
111
+ "properties": {
112
+ "token": MP_TOKEN,
113
+ "distinct_id": _distinct_id,
114
+ "time": int(time.time()),
115
+ "$ip": 0, # disable Mixpanel geolocation
116
+ "dulus_version": _dulus_version,
117
+ "os": platform.system(),
118
+ "python": f"{sys.version_info.major}.{sys.version_info.minor}",
119
+ **(properties or {}),
120
+ },
121
+ }
122
+
123
+ def _send() -> None:
124
+ try:
125
+ from urllib.request import Request, urlopen
126
+ from urllib.parse import urlencode
127
+
128
+ data = urlencode(
129
+ {"data": base64.b64encode(json.dumps([payload]).encode()).decode()}
130
+ ).encode()
131
+ req = Request(_MP_ENDPOINT, data=data, method="POST")
132
+ urlopen(req, timeout=4).read()
133
+ except Exception:
134
+ pass # telemetry must never break Dulus
135
+
136
+ threading.Thread(target=_send, daemon=True, name="telemetry").start()
137
+
138
+
139
+ def track_session_start(config: dict) -> None:
140
+ """Convenience: one event per REPL boot (enough for DAU/MAU counts)."""
141
+ track("session_start", {
142
+ "provider": str(config.get("provider", "")),
143
+ "model": str(config.get("model", "")),
144
+ })
145
+
146
+
147
+ def track_message_sent(model: str = "") -> None:
148
+ """One event per user prompt sent to the LLM (no content — count only)."""
149
+ track("message_sent", {"model": model})
150
+
151
+
152
+ def track_tool_used(tool_name: str) -> None:
153
+ """One event per tool invocation (tool NAME only — never inputs)."""
154
+ track("tool_used", {"tool": tool_name})
155
+
156
+
157
+ def track_command_used(command: str) -> None:
158
+ """One event per slash command (command NAME only — never args)."""
159
+ track("command_used", {"command": command})
160
+
161
+
162
+ def track_model_selected(model: str, provider: str = "") -> None:
163
+ """Fired when the user switches models via /model."""
164
+ track("model_selected", {"model": model, "provider": provider})
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dulus
3
- Version: 3.7.0
3
+ Version: 3.7.1
4
4
  Summary: Use IA as an agent without an API key. $0. Harvest your browser session for Gemini (guest, no login), Claude.ai, Claude Code, Kimi.com, Qwen, DeepSeek — drive them like an API, no per-token billing. Plus LiteLLM (100+ paid providers), local models via Ollama, /lang in 34 languages, Mesa Redonda, voice, OCR, MemPalace, embedded sandbox OS.
5
5
  Author: KevRojo
6
6
  License: GPL-3.0
@@ -130,12 +130,12 @@ dulus_tools/background_tasks.py
130
130
  dulus_tools/clipboard_utils.py
131
131
  dulus_tools/diff_visualizer.py
132
132
  dulus_tools/export_import.py
133
- dulus_tools/fs_compass.py
134
133
  dulus_tools/hook_engine.py
135
134
  dulus_tools/notification_manager.py
136
135
  dulus_tools/session_fork.py
137
136
  dulus_tools/shell_mode.py
138
137
  dulus_tools/todo_visualizer.py
138
+ dulus_tools/tree_ls.py
139
139
  dulus_tools/wire_events.py
140
140
  dulus_tools/yolo_mode.py
141
141
  gui/__init__.py
@@ -294,7 +294,6 @@ tests/test_diff_view.py
294
294
  tests/test_diff_visualization.py
295
295
  tests/test_display_blocks.py
296
296
  tests/test_export_import.py
297
- tests/test_fs_compass.py
298
297
  tests/test_hook_engine.py
299
298
  tests/test_injection_fix.py
300
299
  tests/test_license.py
@@ -313,6 +312,7 @@ tests/test_think_tool.py
313
312
  tests/test_todo_tool.py
314
313
  tests/test_todo_visualization.py
315
314
  tests/test_tool_registry.py
315
+ tests/test_tree_ls.py
316
316
  tests/test_voice.py
317
317
  tests/test_wire_events.py
318
318
  ui/__init__.py