dulus 0.2.23__tar.gz → 0.2.24__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.23/dulus.egg-info → dulus-0.2.24}/PKG-INFO +2 -2
  2. {dulus-0.2.23 → dulus-0.2.24}/README.md +1 -1
  3. {dulus-0.2.23 → dulus-0.2.24}/docs/news.md +7 -0
  4. {dulus-0.2.23 → dulus-0.2.24/dulus.egg-info}/PKG-INFO +2 -2
  5. {dulus-0.2.23 → dulus-0.2.24}/dulus.py +1 -1
  6. {dulus-0.2.23 → dulus-0.2.24}/plugin/autoadapter.py +30 -2
  7. {dulus-0.2.23 → dulus-0.2.24}/pyproject.toml +1 -1
  8. {dulus-0.2.23 → dulus-0.2.24}/LICENSE +0 -0
  9. {dulus-0.2.23 → dulus-0.2.24}/MANIFEST.in +0 -0
  10. {dulus-0.2.23 → dulus-0.2.24}/agent.py +0 -0
  11. {dulus-0.2.23 → dulus-0.2.24}/backend/__init__.py +0 -0
  12. {dulus-0.2.23 → dulus-0.2.24}/backend/compressor.py +0 -0
  13. {dulus-0.2.23 → dulus-0.2.24}/backend/context.py +0 -0
  14. {dulus-0.2.23 → dulus-0.2.24}/backend/githook.py +0 -0
  15. {dulus-0.2.23 → dulus-0.2.24}/backend/marketplace.py +0 -0
  16. {dulus-0.2.23 → dulus-0.2.24}/backend/mempalace_bridge.py +0 -0
  17. {dulus-0.2.23 → dulus-0.2.24}/backend/personas.py +0 -0
  18. {dulus-0.2.23 → dulus-0.2.24}/backend/plugins.py +0 -0
  19. {dulus-0.2.23 → dulus-0.2.24}/backend/server.py +0 -0
  20. {dulus-0.2.23 → dulus-0.2.24}/backend/tasks.py +0 -0
  21. {dulus-0.2.23 → dulus-0.2.24}/batch_api.py +0 -0
  22. {dulus-0.2.23 → dulus-0.2.24}/checkpoint/__init__.py +0 -0
  23. {dulus-0.2.23 → dulus-0.2.24}/checkpoint/hooks.py +0 -0
  24. {dulus-0.2.23 → dulus-0.2.24}/checkpoint/store.py +0 -0
  25. {dulus-0.2.23 → dulus-0.2.24}/checkpoint/types.py +0 -0
  26. {dulus-0.2.23 → dulus-0.2.24}/claude_code_watcher.py +0 -0
  27. {dulus-0.2.23 → dulus-0.2.24}/clipboard_utils.py +0 -0
  28. {dulus-0.2.23 → dulus-0.2.24}/cloudsave.py +0 -0
  29. {dulus-0.2.23 → dulus-0.2.24}/common.py +0 -0
  30. {dulus-0.2.23 → dulus-0.2.24}/compaction.py +0 -0
  31. {dulus-0.2.23 → dulus-0.2.24}/config.py +0 -0
  32. {dulus-0.2.23 → dulus-0.2.24}/context.py +0 -0
  33. {dulus-0.2.23 → dulus-0.2.24}/data/__init__.py +0 -0
  34. {dulus-0.2.23 → dulus-0.2.24}/data/active_persona.json +0 -0
  35. {dulus-0.2.23 → dulus-0.2.24}/data/context.json +0 -0
  36. {dulus-0.2.23 → dulus-0.2.24}/data/marketplace.json +0 -0
  37. {dulus-0.2.23 → dulus-0.2.24}/data/personas.json +0 -0
  38. {dulus-0.2.23 → dulus-0.2.24}/data/plugins/__init__.py +0 -0
  39. {dulus-0.2.23 → dulus-0.2.24}/data/plugins/composio/__init__.py +0 -0
  40. {dulus-0.2.23 → dulus-0.2.24}/data/plugins/composio/composio_plugin/__init__.py +0 -0
  41. {dulus-0.2.23 → dulus-0.2.24}/data/plugins/composio/composio_plugin/session_manager.py +0 -0
  42. {dulus-0.2.23 → dulus-0.2.24}/data/plugins/composio/composio_plugin/tool_generator.py +0 -0
  43. {dulus-0.2.23 → dulus-0.2.24}/data/plugins/composio/plugin.json +0 -0
  44. {dulus-0.2.23 → dulus-0.2.24}/data/plugins/composio/plugin_tool.py +0 -0
  45. {dulus-0.2.23 → dulus-0.2.24}/data/tasks.json +0 -0
  46. {dulus-0.2.23 → dulus-0.2.24}/docs/README.md +0 -0
  47. {dulus-0.2.23 → dulus-0.2.24}/docs/__init__.py +0 -0
  48. {dulus-0.2.23 → dulus-0.2.24}/docs/api.html +0 -0
  49. {dulus-0.2.23 → dulus-0.2.24}/docs/architecture.md +0 -0
  50. {dulus-0.2.23 → dulus-0.2.24}/docs/azure-speech-template.json +0 -0
  51. {dulus-0.2.23 → dulus-0.2.24}/docs/dashboard/index.html +0 -0
  52. {dulus-0.2.23 → dulus-0.2.24}/docs/divider.svg +0 -0
  53. {dulus-0.2.23 → dulus-0.2.24}/docs/generate.py +0 -0
  54. {dulus-0.2.23 → dulus-0.2.24}/docs/hero.svg +0 -0
  55. {dulus-0.2.23 → dulus-0.2.24}/docs/index.html +0 -0
  56. {dulus-0.2.23 → dulus-0.2.24}/docs/nvidia-models.svg +0 -0
  57. {dulus-0.2.23 → dulus-0.2.24}/docs/particle-playground.html +0 -0
  58. {dulus-0.2.23 → dulus-0.2.24}/docs/personas/index.html +0 -0
  59. {dulus-0.2.23 → dulus-0.2.24}/docs/poetry-banner.png +0 -0
  60. {dulus-0.2.23 → dulus-0.2.24}/docs/preview.html +0 -0
  61. {dulus-0.2.23 → dulus-0.2.24}/docs/sec-agents.svg +0 -0
  62. {dulus-0.2.23 → dulus-0.2.24}/docs/sec-brainstorm.svg +0 -0
  63. {dulus-0.2.23 → dulus-0.2.24}/docs/sec-bridges.svg +0 -0
  64. {dulus-0.2.23 → dulus-0.2.24}/docs/sec-features.svg +0 -0
  65. {dulus-0.2.23 → dulus-0.2.24}/docs/sec-freetier.svg +0 -0
  66. {dulus-0.2.23 → dulus-0.2.24}/docs/sec-memory.svg +0 -0
  67. {dulus-0.2.23 → dulus-0.2.24}/docs/sec-models.svg +0 -0
  68. {dulus-0.2.23 → dulus-0.2.24}/docs/sec-perms.svg +0 -0
  69. {dulus-0.2.23 → dulus-0.2.24}/docs/sec-plugins.svg +0 -0
  70. {dulus-0.2.23 → dulus-0.2.24}/docs/sec-quickstart.svg +0 -0
  71. {dulus-0.2.23 → dulus-0.2.24}/docs/sec-ssj.svg +0 -0
  72. {dulus-0.2.23 → dulus-0.2.24}/docs/spinners.svg +0 -0
  73. {dulus-0.2.23 → dulus-0.2.24}/docs/split-pane.svg +0 -0
  74. {dulus-0.2.23 → dulus-0.2.24}/docs/terminal-boot.svg +0 -0
  75. {dulus-0.2.23 → dulus-0.2.24}/docs/uploads/particle-playground.html +0 -0
  76. {dulus-0.2.23 → dulus-0.2.24}/dulus.egg-info/SOURCES.txt +0 -0
  77. {dulus-0.2.23 → dulus-0.2.24}/dulus.egg-info/dependency_links.txt +0 -0
  78. {dulus-0.2.23 → dulus-0.2.24}/dulus.egg-info/entry_points.txt +0 -0
  79. {dulus-0.2.23 → dulus-0.2.24}/dulus.egg-info/requires.txt +0 -0
  80. {dulus-0.2.23 → dulus-0.2.24}/dulus.egg-info/top_level.txt +0 -0
  81. {dulus-0.2.23 → dulus-0.2.24}/dulus_gui.py +0 -0
  82. {dulus-0.2.23 → dulus-0.2.24}/dulus_mcp/__init__.py +0 -0
  83. {dulus-0.2.23 → dulus-0.2.24}/dulus_mcp/client.py +0 -0
  84. {dulus-0.2.23 → dulus-0.2.24}/dulus_mcp/config.py +0 -0
  85. {dulus-0.2.23 → dulus-0.2.24}/dulus_mcp/tools.py +0 -0
  86. {dulus-0.2.23 → dulus-0.2.24}/dulus_mcp/types.py +0 -0
  87. {dulus-0.2.23 → dulus-0.2.24}/gui/__init__.py +0 -0
  88. {dulus-0.2.23 → dulus-0.2.24}/gui/agent_bridge.py +0 -0
  89. {dulus-0.2.23 → dulus-0.2.24}/gui/chat_widget.py +0 -0
  90. {dulus-0.2.23 → dulus-0.2.24}/gui/main_window.py +0 -0
  91. {dulus-0.2.23 → dulus-0.2.24}/gui/personas.py +0 -0
  92. {dulus-0.2.23 → dulus-0.2.24}/gui/session_utils.py +0 -0
  93. {dulus-0.2.23 → dulus-0.2.24}/gui/settings_dialog.py +0 -0
  94. {dulus-0.2.23 → dulus-0.2.24}/gui/sidebar.py +0 -0
  95. {dulus-0.2.23 → dulus-0.2.24}/gui/tasks_view.py +0 -0
  96. {dulus-0.2.23 → dulus-0.2.24}/gui/themes.py +0 -0
  97. {dulus-0.2.23 → dulus-0.2.24}/gui/tool_panel.py +0 -0
  98. {dulus-0.2.23 → dulus-0.2.24}/input.py +0 -0
  99. {dulus-0.2.23 → dulus-0.2.24}/license_manager.py +0 -0
  100. {dulus-0.2.23 → dulus-0.2.24}/memory/__init__.py +0 -0
  101. {dulus-0.2.23 → dulus-0.2.24}/memory/audit.py +0 -0
  102. {dulus-0.2.23 → dulus-0.2.24}/memory/consolidator.py +0 -0
  103. {dulus-0.2.23 → dulus-0.2.24}/memory/context.py +0 -0
  104. {dulus-0.2.23 → dulus-0.2.24}/memory/offload.py +0 -0
  105. {dulus-0.2.23 → dulus-0.2.24}/memory/palace.py +0 -0
  106. {dulus-0.2.23 → dulus-0.2.24}/memory/scan.py +0 -0
  107. {dulus-0.2.23 → dulus-0.2.24}/memory/sessions.py +0 -0
  108. {dulus-0.2.23 → dulus-0.2.24}/memory/store.py +0 -0
  109. {dulus-0.2.23 → dulus-0.2.24}/memory/tools.py +0 -0
  110. {dulus-0.2.23 → dulus-0.2.24}/memory/types.py +0 -0
  111. {dulus-0.2.23 → dulus-0.2.24}/memory/vector_search.py +0 -0
  112. {dulus-0.2.23 → dulus-0.2.24}/multi_agent/__init__.py +0 -0
  113. {dulus-0.2.23 → dulus-0.2.24}/multi_agent/subagent.py +0 -0
  114. {dulus-0.2.23 → dulus-0.2.24}/multi_agent/tools.py +0 -0
  115. {dulus-0.2.23 → dulus-0.2.24}/offload_helper.py +0 -0
  116. {dulus-0.2.23 → dulus-0.2.24}/plugin/__init__.py +0 -0
  117. {dulus-0.2.23 → dulus-0.2.24}/plugin/loader.py +0 -0
  118. {dulus-0.2.23 → dulus-0.2.24}/plugin/recommend.py +0 -0
  119. {dulus-0.2.23 → dulus-0.2.24}/plugin/store.py +0 -0
  120. {dulus-0.2.23 → dulus-0.2.24}/plugin/types.py +0 -0
  121. {dulus-0.2.23 → dulus-0.2.24}/providers.py +0 -0
  122. {dulus-0.2.23 → dulus-0.2.24}/setup.cfg +0 -0
  123. {dulus-0.2.23 → dulus-0.2.24}/skill/__init__.py +0 -0
  124. {dulus-0.2.23 → dulus-0.2.24}/skill/builtin.py +0 -0
  125. {dulus-0.2.23 → dulus-0.2.24}/skill/clawhub.py +0 -0
  126. {dulus-0.2.23 → dulus-0.2.24}/skill/executor.py +0 -0
  127. {dulus-0.2.23 → dulus-0.2.24}/skill/loader.py +0 -0
  128. {dulus-0.2.23 → dulus-0.2.24}/skill/tools.py +0 -0
  129. {dulus-0.2.23 → dulus-0.2.24}/skills.py +0 -0
  130. {dulus-0.2.23 → dulus-0.2.24}/spinner.py +0 -0
  131. {dulus-0.2.23 → dulus-0.2.24}/string_utils.py +0 -0
  132. {dulus-0.2.23 → dulus-0.2.24}/subagent.py +0 -0
  133. {dulus-0.2.23 → dulus-0.2.24}/task/__init__.py +0 -0
  134. {dulus-0.2.23 → dulus-0.2.24}/task/store.py +0 -0
  135. {dulus-0.2.23 → dulus-0.2.24}/task/tools.py +0 -0
  136. {dulus-0.2.23 → dulus-0.2.24}/task/types.py +0 -0
  137. {dulus-0.2.23 → dulus-0.2.24}/tests/test_checkpoint.py +0 -0
  138. {dulus-0.2.23 → dulus-0.2.24}/tests/test_compaction.py +0 -0
  139. {dulus-0.2.23 → dulus-0.2.24}/tests/test_diff_view.py +0 -0
  140. {dulus-0.2.23 → dulus-0.2.24}/tests/test_injection_fix.py +0 -0
  141. {dulus-0.2.23 → dulus-0.2.24}/tests/test_license.py +0 -0
  142. {dulus-0.2.23 → dulus-0.2.24}/tests/test_mcp.py +0 -0
  143. {dulus-0.2.23 → dulus-0.2.24}/tests/test_memory.py +0 -0
  144. {dulus-0.2.23 → dulus-0.2.24}/tests/test_plugin.py +0 -0
  145. {dulus-0.2.23 → dulus-0.2.24}/tests/test_skills.py +0 -0
  146. {dulus-0.2.23 → dulus-0.2.24}/tests/test_subagent.py +0 -0
  147. {dulus-0.2.23 → dulus-0.2.24}/tests/test_task.py +0 -0
  148. {dulus-0.2.23 → dulus-0.2.24}/tests/test_telegram_buffer.py +0 -0
  149. {dulus-0.2.23 → dulus-0.2.24}/tests/test_tool_registry.py +0 -0
  150. {dulus-0.2.23 → dulus-0.2.24}/tests/test_voice.py +0 -0
  151. {dulus-0.2.23 → dulus-0.2.24}/tmux_offloader.py +0 -0
  152. {dulus-0.2.23 → dulus-0.2.24}/tmux_tools.py +0 -0
  153. {dulus-0.2.23 → dulus-0.2.24}/tool_registry.py +0 -0
  154. {dulus-0.2.23 → dulus-0.2.24}/tools.py +0 -0
  155. {dulus-0.2.23 → dulus-0.2.24}/ui/__init__.py +0 -0
  156. {dulus-0.2.23 → dulus-0.2.24}/ui/input.py +0 -0
  157. {dulus-0.2.23 → dulus-0.2.24}/ui/render.py +0 -0
  158. {dulus-0.2.23 → dulus-0.2.24}/voice/__init__.py +0 -0
  159. {dulus-0.2.23 → dulus-0.2.24}/voice/keyterms.py +0 -0
  160. {dulus-0.2.23 → dulus-0.2.24}/voice/recorder.py +0 -0
  161. {dulus-0.2.23 → dulus-0.2.24}/voice/stt.py +0 -0
  162. {dulus-0.2.23 → dulus-0.2.24}/voice/tts.py +0 -0
  163. {dulus-0.2.23 → dulus-0.2.24}/webchat.py +0 -0
  164. {dulus-0.2.23 → dulus-0.2.24}/webchat_server.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dulus
3
- Version: 0.2.23
3
+ Version: 0.2.24
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.23-ff6b1f?style=flat-square&labelColor=07070a" alt="version"/>
72
+ <img src="https://img.shields.io/badge/version-v0.2.24-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"/>
@@ -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.23-ff6b1f?style=flat-square&labelColor=07070a" alt="version"/>
25
+ <img src="https://img.shields.io/badge/version-v0.2.24-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"/>
@@ -3,6 +3,13 @@
3
3
  ## 🔥🔥🔥 News (Pacific Time)
4
4
 
5
5
 
6
+ - May 09, 2026 (**v0.2.24**): **Auto-adapter prompt — 5 fixes from a sherlock postmortem**
7
+ - **Reconciled `limit` default** — the prompt had two contradictory rules ("default: 50, max: 200" vs "default: 10, NOT 50"). Models burned tokens reasoning about which to follow. Unified on `default: 10, hard max: 200` everywhere.
8
+ - **"READ the source first" rule** at the top of the wrapper guidelines. Adapters were inferring upstream function signatures from class names and shipping plugins that compile/import/export cleanly but crash at runtime due to type-shape mismatches. Now the prompt explicitly tells the model to read the consumer code (`param.get(...)` / `for x in param`) before guessing shapes.
9
+ - **Notifier/callback pattern hint** — when the upstream library has a notify/callback class, prefer collecting results via that callback over parsing the return value. Callbacks tend to stay stable; return shapes drift between versions.
10
+ - **`ADAPTATION_GUIDE.md` now requires a `## Type Contracts` section** documenting the exact shape of every non-trivial parameter. Read by the verifier and by future re-adaptations — eliminates blind re-guessing.
11
+ - **Verifier checklist explicitly flags the smoke test as THE BAR.** Compile / import / exports / ToolDef-shape are necessary but not sufficient. The new header in `ADAPTATION_TODO.md` warns the model not to celebrate after the syntactic checks — most real bugs are type-shape mismatches that only the smoke test catches.
12
+
6
13
  - May 09, 2026 (**v0.2.23**): **Auto-adapter teaches new plugins to declare TmuxOffload-worthy tools**
7
14
  - **The adapter prompt now requires** the model to estimate per-tool runtime. Any tool that typically takes more than ~15 seconds (sherlock, holehe, OSINT crawls, video downloads, full-repo analysis, etc.) must end its `description` with the literal marker `[long-running — wrap in TmuxOffload]`.
8
15
  - **System prompt now honors that marker** at runtime. When the agent sees a tool with that suffix, it wraps the call in TmuxOffload automatically instead of blocking the REPL. No more 90-second sherlock freezes pretending to be productive.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dulus
3
- Version: 0.2.23
3
+ Version: 0.2.24
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.23-ff6b1f?style=flat-square&labelColor=07070a" alt="version"/>
72
+ <img src="https://img.shields.io/badge/version-v0.2.24-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"/>
@@ -218,7 +218,7 @@ try:
218
218
  from importlib.metadata import version as _pkg_version
219
219
  VERSION = _pkg_version("dulus")
220
220
  except Exception:
221
- VERSION = "0.2.23" # dev fallback — keep in sync with pyproject.toml
221
+ VERSION = "0.2.24" # dev fallback — keep in sync with pyproject.toml
222
222
 
223
223
  # ── ANSI helpers (used even with rich for non-markdown output) ─────────────
224
224
  from common import C, clr, info, ok, warn, err, stream_thinking, print_tool_start, print_tool_end, sanitize_text
@@ -250,6 +250,13 @@ GOAL: Generate `plugin.json`, `plugin_tool.py`, and `ADAPTATION_GUIDE.md`.
250
250
 
251
251
  GUIDELINES FOR plugin_tool.py:
252
252
 
253
+ 0. READ THE SOURCE FIRST (critical — skip and you'll waste 10+ retry rounds):
254
+ - Before writing the wrapper, READ the actual function/class definitions you'll be calling.
255
+ - Note the EXACT shape each parameter expects: raw dict-of-dicts vs object-of-objects vs list of objects.
256
+ - DO NOT infer shapes from class names. Read the consumer code that does `param.get(...)` or `for x in param: ...`.
257
+ - When the upstream library has a notifier/callback/observer class, PREFER collecting results via that callback over parsing the return value — callbacks are usually consistent across versions, return shapes are not.
258
+ - Common gotcha: a class called `XInformation` often *wraps* the raw dict in `.information` or `.data`. The downstream function may expect the raw dict, not the wrapper. Verify by reading the function body.
259
+
253
260
  1. EXPORTS (mandatory):
254
261
  - `TOOL_DEFS`: list of `ToolDef(name, schema, func)` objects
255
262
  - `TOOL_SCHEMAS`: `[t.schema for t in TOOL_DEFS]`
@@ -272,7 +279,7 @@ GUIDELINES FOR plugin_tool.py:
272
279
 
273
280
  4. SCHEMA DESIGN:
274
281
  - Each param gets its own property. Never bundle into single "data" string
275
- - Include `limit`/`max_results` (default: 10, NOT 50) and `verbose` (default: False) on every tool
282
+ - Include `limit`/`max_results` (default: 10, hard max: 200) and `verbose` (default: False) on every tool
276
283
 
277
284
  5. TOOL GRANULARITY:
278
285
  - Multiple specific tools > one mega-tool
@@ -362,6 +369,19 @@ TMUX-OFFLOAD HINT (important for UX):
362
369
  Respond with the delimited format:
363
370
  ---FILE: ADAPTATION_GUIDE.md---
364
371
  (Overview, tool design decisions, error patterns, validation)
372
+
373
+ The ADAPTATION_GUIDE.md MUST include a `## Type Contracts` section that documents,
374
+ for each upstream function/class you call, the EXACT shape of every non-trivial
375
+ parameter. Example:
376
+
377
+ ## Type Contracts
378
+ - `sherlock(username, site_data, ...)` expects `site_data: Dict[str, Dict[str, Any]]`
379
+ (NOT `Dict[str, SiteInformation]` — extract `.information` from each SiteInformation first).
380
+ - `notifier.update(result)` is called once per site with a `QueryResult` object.
381
+ Collect via a `_SilentNotify(QueryNotify)` subclass instead of parsing the return dict.
382
+
383
+ This section is read by the verifier and by future re-adaptations, so be precise.
384
+
365
385
  ---FILE: plugin.json---
366
386
  (JSON manifest)
367
387
  ---FILE: plugin_tool.py---
@@ -399,7 +419,7 @@ Respond with the delimited format:
399
419
  "- Always encoding='utf-8', errors='replace' for file/subprocess I/O\n"
400
420
  "- Never lowercase true/false/null in Python — always True/False/None\n\n"
401
421
  "TOKEN OPTIMIZATION RULES — plugins MUST be efficient:\n"
402
- "- Every tool MUST accept a 'limit' or 'max_results' parameter (default: 50, max: 200)\n"
422
+ "- Every tool MUST accept a 'limit' or 'max_results' parameter (default: 10, hard max: 200)\n"
403
423
  "- Every tool MUST accept a 'verbose' parameter (default: False)\n"
404
424
  "- When verbose=False, return ONLY essential data — no debug info, no banners\n"
405
425
  "- Lists/arrays MUST be truncated before returning — never return unlimited items\n"
@@ -807,6 +827,14 @@ def _write_todo_file(plugin_dir: Path, safe_name: str, items: list[dict]) -> Pat
807
827
  "Auto-generated checklist verifying the AI-generated plugin works.",
808
828
  "Each task is verified by the adapter worker; failures trigger a fix attempt.",
809
829
  "",
830
+ "⚠ THE BAR IS THE SMOKE TEST. Compile / import / exports / ToolDef-shape",
831
+ "checks are necessary but NOT sufficient — they only prove the file is",
832
+ "syntactically a Python module that exports something callable. They do",
833
+ "NOT prove the wrapper passes the right shapes to upstream functions.",
834
+ "If a smoke test fails after the syntactic checks pass, the bug is almost",
835
+ "always a TYPE-SHAPE mismatch (e.g. passing wrapper objects where the",
836
+ "function expected raw dicts). Re-read the source code before guessing.",
837
+ "",
810
838
  ]
811
839
  for item in items:
812
840
  lines.append(f"- [ ] {item['title']}")
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "dulus"
7
- version = "0.2.23"
7
+ version = "0.2.24"
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