dulus 0.2.31__tar.gz → 0.2.32__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 (164) hide show
  1. {dulus-0.2.31/dulus.egg-info → dulus-0.2.32}/PKG-INFO +1 -1
  2. {dulus-0.2.31 → dulus-0.2.32/dulus.egg-info}/PKG-INFO +1 -1
  3. {dulus-0.2.31 → dulus-0.2.32}/dulus.py +64 -9
  4. {dulus-0.2.31 → dulus-0.2.32}/pyproject.toml +1 -1
  5. {dulus-0.2.31 → dulus-0.2.32}/LICENSE +0 -0
  6. {dulus-0.2.31 → dulus-0.2.32}/MANIFEST.in +0 -0
  7. {dulus-0.2.31 → dulus-0.2.32}/README.md +0 -0
  8. {dulus-0.2.31 → dulus-0.2.32}/agent.py +0 -0
  9. {dulus-0.2.31 → dulus-0.2.32}/backend/__init__.py +0 -0
  10. {dulus-0.2.31 → dulus-0.2.32}/backend/compressor.py +0 -0
  11. {dulus-0.2.31 → dulus-0.2.32}/backend/context.py +0 -0
  12. {dulus-0.2.31 → dulus-0.2.32}/backend/githook.py +0 -0
  13. {dulus-0.2.31 → dulus-0.2.32}/backend/marketplace.py +0 -0
  14. {dulus-0.2.31 → dulus-0.2.32}/backend/mempalace_bridge.py +0 -0
  15. {dulus-0.2.31 → dulus-0.2.32}/backend/personas.py +0 -0
  16. {dulus-0.2.31 → dulus-0.2.32}/backend/plugins.py +0 -0
  17. {dulus-0.2.31 → dulus-0.2.32}/backend/server.py +0 -0
  18. {dulus-0.2.31 → dulus-0.2.32}/backend/tasks.py +0 -0
  19. {dulus-0.2.31 → dulus-0.2.32}/batch_api.py +0 -0
  20. {dulus-0.2.31 → dulus-0.2.32}/checkpoint/__init__.py +0 -0
  21. {dulus-0.2.31 → dulus-0.2.32}/checkpoint/hooks.py +0 -0
  22. {dulus-0.2.31 → dulus-0.2.32}/checkpoint/store.py +0 -0
  23. {dulus-0.2.31 → dulus-0.2.32}/checkpoint/types.py +0 -0
  24. {dulus-0.2.31 → dulus-0.2.32}/claude_code_watcher.py +0 -0
  25. {dulus-0.2.31 → dulus-0.2.32}/clipboard_utils.py +0 -0
  26. {dulus-0.2.31 → dulus-0.2.32}/cloudsave.py +0 -0
  27. {dulus-0.2.31 → dulus-0.2.32}/common.py +0 -0
  28. {dulus-0.2.31 → dulus-0.2.32}/compaction.py +0 -0
  29. {dulus-0.2.31 → dulus-0.2.32}/config.py +0 -0
  30. {dulus-0.2.31 → dulus-0.2.32}/context.py +0 -0
  31. {dulus-0.2.31 → dulus-0.2.32}/data/__init__.py +0 -0
  32. {dulus-0.2.31 → dulus-0.2.32}/data/active_persona.json +0 -0
  33. {dulus-0.2.31 → dulus-0.2.32}/data/context.json +0 -0
  34. {dulus-0.2.31 → dulus-0.2.32}/data/marketplace.json +0 -0
  35. {dulus-0.2.31 → dulus-0.2.32}/data/personas.json +0 -0
  36. {dulus-0.2.31 → dulus-0.2.32}/data/plugins/__init__.py +0 -0
  37. {dulus-0.2.31 → dulus-0.2.32}/data/plugins/composio/__init__.py +0 -0
  38. {dulus-0.2.31 → dulus-0.2.32}/data/plugins/composio/composio_plugin/__init__.py +0 -0
  39. {dulus-0.2.31 → dulus-0.2.32}/data/plugins/composio/composio_plugin/session_manager.py +0 -0
  40. {dulus-0.2.31 → dulus-0.2.32}/data/plugins/composio/composio_plugin/tool_generator.py +0 -0
  41. {dulus-0.2.31 → dulus-0.2.32}/data/plugins/composio/plugin.json +0 -0
  42. {dulus-0.2.31 → dulus-0.2.32}/data/plugins/composio/plugin_tool.py +0 -0
  43. {dulus-0.2.31 → dulus-0.2.32}/data/tasks.json +0 -0
  44. {dulus-0.2.31 → dulus-0.2.32}/docs/README.md +0 -0
  45. {dulus-0.2.31 → dulus-0.2.32}/docs/__init__.py +0 -0
  46. {dulus-0.2.31 → dulus-0.2.32}/docs/api.html +0 -0
  47. {dulus-0.2.31 → dulus-0.2.32}/docs/architecture.md +0 -0
  48. {dulus-0.2.31 → dulus-0.2.32}/docs/azure-speech-template.json +0 -0
  49. {dulus-0.2.31 → dulus-0.2.32}/docs/dashboard/index.html +0 -0
  50. {dulus-0.2.31 → dulus-0.2.32}/docs/divider.svg +0 -0
  51. {dulus-0.2.31 → dulus-0.2.32}/docs/generate.py +0 -0
  52. {dulus-0.2.31 → dulus-0.2.32}/docs/hero.svg +0 -0
  53. {dulus-0.2.31 → dulus-0.2.32}/docs/index.html +0 -0
  54. {dulus-0.2.31 → dulus-0.2.32}/docs/news.md +0 -0
  55. {dulus-0.2.31 → dulus-0.2.32}/docs/nvidia-models.svg +0 -0
  56. {dulus-0.2.31 → dulus-0.2.32}/docs/particle-playground.html +0 -0
  57. {dulus-0.2.31 → dulus-0.2.32}/docs/personas/index.html +0 -0
  58. {dulus-0.2.31 → dulus-0.2.32}/docs/poetry-banner.png +0 -0
  59. {dulus-0.2.31 → dulus-0.2.32}/docs/preview.html +0 -0
  60. {dulus-0.2.31 → dulus-0.2.32}/docs/sec-agents.svg +0 -0
  61. {dulus-0.2.31 → dulus-0.2.32}/docs/sec-brainstorm.svg +0 -0
  62. {dulus-0.2.31 → dulus-0.2.32}/docs/sec-bridges.svg +0 -0
  63. {dulus-0.2.31 → dulus-0.2.32}/docs/sec-features.svg +0 -0
  64. {dulus-0.2.31 → dulus-0.2.32}/docs/sec-freetier.svg +0 -0
  65. {dulus-0.2.31 → dulus-0.2.32}/docs/sec-memory.svg +0 -0
  66. {dulus-0.2.31 → dulus-0.2.32}/docs/sec-models.svg +0 -0
  67. {dulus-0.2.31 → dulus-0.2.32}/docs/sec-perms.svg +0 -0
  68. {dulus-0.2.31 → dulus-0.2.32}/docs/sec-plugins.svg +0 -0
  69. {dulus-0.2.31 → dulus-0.2.32}/docs/sec-quickstart.svg +0 -0
  70. {dulus-0.2.31 → dulus-0.2.32}/docs/sec-ssj.svg +0 -0
  71. {dulus-0.2.31 → dulus-0.2.32}/docs/spinners.svg +0 -0
  72. {dulus-0.2.31 → dulus-0.2.32}/docs/split-pane.svg +0 -0
  73. {dulus-0.2.31 → dulus-0.2.32}/docs/terminal-boot.svg +0 -0
  74. {dulus-0.2.31 → dulus-0.2.32}/docs/uploads/particle-playground.html +0 -0
  75. {dulus-0.2.31 → dulus-0.2.32}/dulus.egg-info/SOURCES.txt +0 -0
  76. {dulus-0.2.31 → dulus-0.2.32}/dulus.egg-info/dependency_links.txt +0 -0
  77. {dulus-0.2.31 → dulus-0.2.32}/dulus.egg-info/entry_points.txt +0 -0
  78. {dulus-0.2.31 → dulus-0.2.32}/dulus.egg-info/requires.txt +0 -0
  79. {dulus-0.2.31 → dulus-0.2.32}/dulus.egg-info/top_level.txt +0 -0
  80. {dulus-0.2.31 → dulus-0.2.32}/dulus_gui.py +0 -0
  81. {dulus-0.2.31 → dulus-0.2.32}/dulus_mcp/__init__.py +0 -0
  82. {dulus-0.2.31 → dulus-0.2.32}/dulus_mcp/client.py +0 -0
  83. {dulus-0.2.31 → dulus-0.2.32}/dulus_mcp/config.py +0 -0
  84. {dulus-0.2.31 → dulus-0.2.32}/dulus_mcp/tools.py +0 -0
  85. {dulus-0.2.31 → dulus-0.2.32}/dulus_mcp/types.py +0 -0
  86. {dulus-0.2.31 → dulus-0.2.32}/gui/__init__.py +0 -0
  87. {dulus-0.2.31 → dulus-0.2.32}/gui/agent_bridge.py +0 -0
  88. {dulus-0.2.31 → dulus-0.2.32}/gui/chat_widget.py +0 -0
  89. {dulus-0.2.31 → dulus-0.2.32}/gui/main_window.py +0 -0
  90. {dulus-0.2.31 → dulus-0.2.32}/gui/personas.py +0 -0
  91. {dulus-0.2.31 → dulus-0.2.32}/gui/session_utils.py +0 -0
  92. {dulus-0.2.31 → dulus-0.2.32}/gui/settings_dialog.py +0 -0
  93. {dulus-0.2.31 → dulus-0.2.32}/gui/sidebar.py +0 -0
  94. {dulus-0.2.31 → dulus-0.2.32}/gui/tasks_view.py +0 -0
  95. {dulus-0.2.31 → dulus-0.2.32}/gui/themes.py +0 -0
  96. {dulus-0.2.31 → dulus-0.2.32}/gui/tool_panel.py +0 -0
  97. {dulus-0.2.31 → dulus-0.2.32}/input.py +0 -0
  98. {dulus-0.2.31 → dulus-0.2.32}/license_manager.py +0 -0
  99. {dulus-0.2.31 → dulus-0.2.32}/memory/__init__.py +0 -0
  100. {dulus-0.2.31 → dulus-0.2.32}/memory/audit.py +0 -0
  101. {dulus-0.2.31 → dulus-0.2.32}/memory/consolidator.py +0 -0
  102. {dulus-0.2.31 → dulus-0.2.32}/memory/context.py +0 -0
  103. {dulus-0.2.31 → dulus-0.2.32}/memory/offload.py +0 -0
  104. {dulus-0.2.31 → dulus-0.2.32}/memory/palace.py +0 -0
  105. {dulus-0.2.31 → dulus-0.2.32}/memory/scan.py +0 -0
  106. {dulus-0.2.31 → dulus-0.2.32}/memory/sessions.py +0 -0
  107. {dulus-0.2.31 → dulus-0.2.32}/memory/store.py +0 -0
  108. {dulus-0.2.31 → dulus-0.2.32}/memory/tools.py +0 -0
  109. {dulus-0.2.31 → dulus-0.2.32}/memory/types.py +0 -0
  110. {dulus-0.2.31 → dulus-0.2.32}/memory/vector_search.py +0 -0
  111. {dulus-0.2.31 → dulus-0.2.32}/multi_agent/__init__.py +0 -0
  112. {dulus-0.2.31 → dulus-0.2.32}/multi_agent/subagent.py +0 -0
  113. {dulus-0.2.31 → dulus-0.2.32}/multi_agent/tools.py +0 -0
  114. {dulus-0.2.31 → dulus-0.2.32}/offload_helper.py +0 -0
  115. {dulus-0.2.31 → dulus-0.2.32}/plugin/__init__.py +0 -0
  116. {dulus-0.2.31 → dulus-0.2.32}/plugin/autoadapter.py +0 -0
  117. {dulus-0.2.31 → dulus-0.2.32}/plugin/loader.py +0 -0
  118. {dulus-0.2.31 → dulus-0.2.32}/plugin/recommend.py +0 -0
  119. {dulus-0.2.31 → dulus-0.2.32}/plugin/store.py +0 -0
  120. {dulus-0.2.31 → dulus-0.2.32}/plugin/types.py +0 -0
  121. {dulus-0.2.31 → dulus-0.2.32}/providers.py +0 -0
  122. {dulus-0.2.31 → dulus-0.2.32}/setup.cfg +0 -0
  123. {dulus-0.2.31 → dulus-0.2.32}/skill/__init__.py +0 -0
  124. {dulus-0.2.31 → dulus-0.2.32}/skill/builtin.py +0 -0
  125. {dulus-0.2.31 → dulus-0.2.32}/skill/clawhub.py +0 -0
  126. {dulus-0.2.31 → dulus-0.2.32}/skill/executor.py +0 -0
  127. {dulus-0.2.31 → dulus-0.2.32}/skill/loader.py +0 -0
  128. {dulus-0.2.31 → dulus-0.2.32}/skill/tools.py +0 -0
  129. {dulus-0.2.31 → dulus-0.2.32}/skills.py +0 -0
  130. {dulus-0.2.31 → dulus-0.2.32}/spinner.py +0 -0
  131. {dulus-0.2.31 → dulus-0.2.32}/string_utils.py +0 -0
  132. {dulus-0.2.31 → dulus-0.2.32}/subagent.py +0 -0
  133. {dulus-0.2.31 → dulus-0.2.32}/task/__init__.py +0 -0
  134. {dulus-0.2.31 → dulus-0.2.32}/task/store.py +0 -0
  135. {dulus-0.2.31 → dulus-0.2.32}/task/tools.py +0 -0
  136. {dulus-0.2.31 → dulus-0.2.32}/task/types.py +0 -0
  137. {dulus-0.2.31 → dulus-0.2.32}/tests/test_checkpoint.py +0 -0
  138. {dulus-0.2.31 → dulus-0.2.32}/tests/test_compaction.py +0 -0
  139. {dulus-0.2.31 → dulus-0.2.32}/tests/test_diff_view.py +0 -0
  140. {dulus-0.2.31 → dulus-0.2.32}/tests/test_injection_fix.py +0 -0
  141. {dulus-0.2.31 → dulus-0.2.32}/tests/test_license.py +0 -0
  142. {dulus-0.2.31 → dulus-0.2.32}/tests/test_mcp.py +0 -0
  143. {dulus-0.2.31 → dulus-0.2.32}/tests/test_memory.py +0 -0
  144. {dulus-0.2.31 → dulus-0.2.32}/tests/test_plugin.py +0 -0
  145. {dulus-0.2.31 → dulus-0.2.32}/tests/test_skills.py +0 -0
  146. {dulus-0.2.31 → dulus-0.2.32}/tests/test_subagent.py +0 -0
  147. {dulus-0.2.31 → dulus-0.2.32}/tests/test_task.py +0 -0
  148. {dulus-0.2.31 → dulus-0.2.32}/tests/test_telegram_buffer.py +0 -0
  149. {dulus-0.2.31 → dulus-0.2.32}/tests/test_tool_registry.py +0 -0
  150. {dulus-0.2.31 → dulus-0.2.32}/tests/test_voice.py +0 -0
  151. {dulus-0.2.31 → dulus-0.2.32}/tmux_offloader.py +0 -0
  152. {dulus-0.2.31 → dulus-0.2.32}/tmux_tools.py +0 -0
  153. {dulus-0.2.31 → dulus-0.2.32}/tool_registry.py +0 -0
  154. {dulus-0.2.31 → dulus-0.2.32}/tools.py +0 -0
  155. {dulus-0.2.31 → dulus-0.2.32}/ui/__init__.py +0 -0
  156. {dulus-0.2.31 → dulus-0.2.32}/ui/input.py +0 -0
  157. {dulus-0.2.31 → dulus-0.2.32}/ui/render.py +0 -0
  158. {dulus-0.2.31 → dulus-0.2.32}/voice/__init__.py +0 -0
  159. {dulus-0.2.31 → dulus-0.2.32}/voice/keyterms.py +0 -0
  160. {dulus-0.2.31 → dulus-0.2.32}/voice/recorder.py +0 -0
  161. {dulus-0.2.31 → dulus-0.2.32}/voice/stt.py +0 -0
  162. {dulus-0.2.31 → dulus-0.2.32}/voice/tts.py +0 -0
  163. {dulus-0.2.31 → dulus-0.2.32}/webchat.py +0 -0
  164. {dulus-0.2.31 → dulus-0.2.32}/webchat_server.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dulus
3
- Version: 0.2.31
3
+ Version: 0.2.32
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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dulus
3
- Version: 0.2.31
3
+ Version: 0.2.32
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
@@ -1688,16 +1688,44 @@ def cmd_bg(args: str, _state, config) -> bool:
1688
1688
  # ── /bg attach ────────────────────────────────────────────────────────
1689
1689
  if sub == "attach":
1690
1690
  pid = _read_pid()
1691
- if not _is_alive(pid):
1692
- warn("Dulus background not running. Use `/bg start` first.")
1691
+ if not _is_alive(pid) or not _ipc_alive():
1692
+ warn("No background daemon running. Use `/bg start` first.")
1693
1693
  return True
1694
- port = config.get("_webchat_port", 5000)
1695
- info("Attach options:")
1696
- info(f" From any shell: dulus \"your prompt\" (joins via IPC)")
1697
- info(f" Browser: http://127.0.0.1:{port}/")
1698
- if _sys.platform != "win32":
1699
- info(f" • Tmux (if used): tmux attach -t dulus-bg")
1700
- info(f" • Tail log: tail -f {BG_LOG}")
1694
+ # Enter a mini-REPL that dispatches to the daemon via IPC
1695
+ ok("Attached to background daemon. Type your prompts (Ctrl+C to detach).")
1696
+ info(f" PID: {pid} | IPC: 127.0.0.1:{DULUS_IPC_PORT}")
1697
+ info(f" Web: http://127.0.0.1:{config.get('_webchat_port', 5000)}/")
1698
+ info(" /exit or /detach to disconnect.")
1699
+ while True:
1700
+ try:
1701
+ line = input(clr(" bg> ", "cyan"))
1702
+ except (KeyboardInterrupt, EOFError):
1703
+ print()
1704
+ info("Detached.")
1705
+ break
1706
+ line = line.strip()
1707
+ if not line:
1708
+ continue
1709
+ if line.lower() in ("/exit", "/detach", "/quit"):
1710
+ info("Detached.")
1711
+ break
1712
+ # Send to daemon via IPC
1713
+ try:
1714
+ s = _socket.create_connection(("127.0.0.1", DULUS_IPC_PORT), timeout=5)
1715
+ s.sendall(_json.dumps({"prompt": line}).encode() + b"\n")
1716
+ s.settimeout(300)
1717
+ buf = b""
1718
+ while b"\n" not in buf:
1719
+ chunk = s.recv(4096)
1720
+ if not chunk:
1721
+ break
1722
+ buf += chunk
1723
+ s.close()
1724
+ resp = _json.loads(buf.split(b"\n")[0])
1725
+ reply = resp.get("response", resp.get("error", "(no response)"))
1726
+ print(reply)
1727
+ except Exception as e:
1728
+ err(f"IPC error: {e}")
1701
1729
  return True
1702
1730
 
1703
1731
  # ── /bg kill ──────────────────────────────────────────────────────────
@@ -5889,6 +5917,33 @@ def _run_daemon(config: dict) -> None:
5889
5917
  err(f"daemon run_query error: {type(_e).__name__}: {_e}")
5890
5918
  config["_run_query_callback"] = _daemon_run_query
5891
5919
 
5920
+ # Register slash-command callback so Telegram and WebChat can run
5921
+ # /commands in daemon mode (without this, slash_cb is None and
5922
+ # commands are silently dropped).
5923
+ def _daemon_handle_slash(line: str):
5924
+ """Process a /command in daemon mode — mirrors the REPL callback."""
5925
+ result = handle_slash(line, state, config)
5926
+ if not isinstance(result, tuple):
5927
+ return "simple"
5928
+ if result[0] == "__brainstorm__":
5929
+ _, brain_prompt, brain_out_file = result
5930
+ _daemon_run_query(brain_prompt)
5931
+ _save_synthesis(state, brain_out_file)
5932
+ _todo_path = str(Path(brain_out_file).parent / "todo_list.txt")
5933
+ _daemon_run_query(
5934
+ f"Based on the Master Plan you just synthesized, generate a todo list file at {_todo_path}. "
5935
+ "Format: one task per line, each starting with '- [ ] '. "
5936
+ "Order by priority. Include ALL actionable items from the plan. "
5937
+ "Use the Write tool to create the file. Do NOT explain, just write the file now."
5938
+ )
5939
+ elif result[0] == "__worker__":
5940
+ _, worker_tasks = result
5941
+ for i, (line_idx, task_text, prompt) in enumerate(worker_tasks):
5942
+ _daemon_run_query(prompt)
5943
+ return "query"
5944
+
5945
+ config["_handle_slash_callback"] = _daemon_handle_slash
5946
+
5892
5947
  # Auto-start the webchat server alongside the daemon — always, by default.
5893
5948
  # The whole point of daemon mode is "headless Dulus serving every entry
5894
5949
  # point at once" (CLI via IPC, browser via WebChat, Telegram via bridge).
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "dulus"
7
- version = "0.2.31"
7
+ version = "0.2.32"
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