dreadnode 2.0.29__tar.gz → 2.0.30__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 (634) hide show
  1. {dreadnode-2.0.29 → dreadnode-2.0.30}/PKG-INFO +1 -1
  2. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/assessment.py +15 -1
  3. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/cli/task.py +127 -4
  4. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/server/model_resolution.py +5 -10
  5. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/tool_format.py +5 -5
  6. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/agents/dreadnode.md +2 -0
  7. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/settings.md +30 -16
  8. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/generators/generator/litellm_.py +17 -1
  9. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/generators/message.py +216 -4
  10. dreadnode-2.0.30/dreadnode/generators/proxy.py +59 -0
  11. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/packaging/task_validation.py +30 -0
  12. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/tools/read.py +89 -14
  13. {dreadnode-2.0.29 → dreadnode-2.0.30}/pyproject.toml +1 -1
  14. {dreadnode-2.0.29 → dreadnode-2.0.30}/.gitignore +0 -0
  15. {dreadnode-2.0.29 → dreadnode-2.0.30}/LICENSE +0 -0
  16. {dreadnode-2.0.29 → dreadnode-2.0.30}/README.md +0 -0
  17. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/__init__.py +0 -0
  18. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/__main__.py +0 -0
  19. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/agents/__init__.py +0 -0
  20. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/agents/agent.py +0 -0
  21. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/agents/events.py +0 -0
  22. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/agents/exceptions.py +0 -0
  23. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/agents/format.py +0 -0
  24. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/agents/hooks.py +0 -0
  25. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/agents/judge.py +0 -0
  26. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/agents/mcp/__init__.py +0 -0
  27. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/agents/mcp/auth.py +0 -0
  28. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/agents/mcp/client.py +0 -0
  29. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/agents/mcp/config.py +0 -0
  30. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/agents/mcp/server.py +0 -0
  31. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/agents/process_judge.py +0 -0
  32. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/agents/reactions.py +0 -0
  33. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/agents/skills.py +0 -0
  34. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/agents/stopping.py +0 -0
  35. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/agents/subagent.py +0 -0
  36. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/agents/tool_resolution.py +0 -0
  37. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/agents/tools.py +0 -0
  38. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/agents/trajectory.py +0 -0
  39. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/__init__.py +0 -0
  40. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/adversarial_reasoning.py +0 -0
  41. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/advpromptier.py +0 -0
  42. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/alignment_faking.py +0 -0
  43. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/analogy_escalation.py +0 -0
  44. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/analytics/__init__.py +0 -0
  45. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/analytics/aggregator.py +0 -0
  46. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/analytics/classifier.py +0 -0
  47. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/analytics/compliance.py +0 -0
  48. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/analytics/engine.py +0 -0
  49. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/analytics/recommendations.py +0 -0
  50. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/analytics/types.py +0 -0
  51. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/aprt_progressive.py +0 -0
  52. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/attention_shifting.py +0 -0
  53. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/autodan_turbo.py +0 -0
  54. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/autoredteamer.py +0 -0
  55. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/beast.py +0 -0
  56. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/compliance/__init__.py +0 -0
  57. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/compliance/atlas.py +0 -0
  58. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/compliance/nist.py +0 -0
  59. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/compliance/owasp.py +0 -0
  60. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/compliance/owasp_agentic.py +0 -0
  61. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/compliance/saif.py +0 -0
  62. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/constants.py +0 -0
  63. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/cot_jailbreak.py +0 -0
  64. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/crescendo.py +0 -0
  65. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/data/__init__.py +0 -0
  66. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/data/assets/audio/adversarial_query.mp3 +0 -0
  67. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/data/assets/image/bomb.jpg +0 -0
  68. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/data/assets/image/meth.png +0 -0
  69. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/data/prompts/adversarial_benchmark_subset.csv +0 -0
  70. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/data/prompts/ai_safety.csv +0 -0
  71. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/data/rubrics/data_exfiltration.yaml +0 -0
  72. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/data/rubrics/goal_hijacking.yaml +0 -0
  73. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/data/rubrics/idor.yaml +0 -0
  74. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/data/rubrics/memory_poisoning.yaml +0 -0
  75. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/data/rubrics/privilege_escalation.yaml +0 -0
  76. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/data/rubrics/rce.yaml +0 -0
  77. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/data/rubrics/scope_creep.yaml +0 -0
  78. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/data/rubrics/tool_chaining.yaml +0 -0
  79. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/data/rubrics/tool_selection_safety.yaml +0 -0
  80. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/data/rubrics/unbounded_agency.yaml +0 -0
  81. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/data/rubrics/web_chatbot_security.yaml +0 -0
  82. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/data/templates/crescendo/variant_1.yaml +0 -0
  83. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/data/templates/crescendo/variant_2.yaml +0 -0
  84. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/data/templates/crescendo/variant_3.yaml +0 -0
  85. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/data/templates/crescendo/variant_4.yaml +0 -0
  86. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/data/templates/crescendo/variant_5.yaml +0 -0
  87. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/deep_inception.py +0 -0
  88. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/drattack.py +0 -0
  89. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/echo_chamber.py +0 -0
  90. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/events.py +0 -0
  91. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/genetic_persona.py +0 -0
  92. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/goat.py +0 -0
  93. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/goat_v2.py +0 -0
  94. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/gptfuzzer.py +0 -0
  95. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/humor_bypass.py +0 -0
  96. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/image.py +0 -0
  97. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/j2_meta.py +0 -0
  98. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/jbdistill.py +0 -0
  99. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/jbfuzz.py +0 -0
  100. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/lrm_autonomous.py +0 -0
  101. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/mapf.py +0 -0
  102. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/multimodal.py +0 -0
  103. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/nexus.py +0 -0
  104. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/pair.py +0 -0
  105. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/persona_hijack.py +0 -0
  106. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/prompt.py +0 -0
  107. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/quantization_safety.py +0 -0
  108. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/rainbow.py +0 -0
  109. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/refusal_aware.py +0 -0
  110. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/renellm.py +0 -0
  111. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/reporting/__init__.py +0 -0
  112. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/reporting/json_report.py +0 -0
  113. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/reporting/llm_summary.py +0 -0
  114. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/reporting/markdown.py +0 -0
  115. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/reward_hacking.py +0 -0
  116. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/salami_slicing.py +0 -0
  117. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/self_persuasion.py +0 -0
  118. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/siren.py +0 -0
  119. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/tap.py +0 -0
  120. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/templatefuzz.py +0 -0
  121. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/tmap_trajectory.py +0 -0
  122. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/trojail.py +0 -0
  123. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/airt/watermark_removal.py +0 -0
  124. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/__init__.py +0 -0
  125. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/api/__init__.py +0 -0
  126. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/api/client.py +0 -0
  127. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/api/models.py +0 -0
  128. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/cli/__init__.py +0 -0
  129. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/cli/airt.py +0 -0
  130. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/cli/args.py +0 -0
  131. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/cli/capability.py +0 -0
  132. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/cli/dataset.py +0 -0
  133. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/cli/environment.py +0 -0
  134. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/cli/evaluation.py +0 -0
  135. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/cli/inference_model.py +0 -0
  136. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/cli/judge.py +0 -0
  137. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/cli/main.py +0 -0
  138. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/cli/model.py +0 -0
  139. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/cli/optimize.py +0 -0
  140. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/cli/runtime.py +0 -0
  141. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/cli/sandbox.py +0 -0
  142. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/cli/secret.py +0 -0
  143. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/cli/session.py +0 -0
  144. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/cli/shared.py +0 -0
  145. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/cli/templates/__init__.py +0 -0
  146. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/cli/templates/init/__init__.py +0 -0
  147. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/cli/templates/init/challenge/Dockerfile +0 -0
  148. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/cli/templates/init/docker-compose.yaml +0 -0
  149. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/cli/templates/init/provision.sh +0 -0
  150. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/cli/templates/init/solution.sh +0 -0
  151. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/cli/templates/init/task-remote.yaml.tmpl +0 -0
  152. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/cli/templates/init/task.yaml.tmpl +0 -0
  153. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/cli/templates/init/teardown.sh +0 -0
  154. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/cli/templates/init/verify.sh +0 -0
  155. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/cli/train.py +0 -0
  156. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/cli/worlds.py +0 -0
  157. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/client/__init__.py +0 -0
  158. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/client/interactive.py +0 -0
  159. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/client/managed_client.py +0 -0
  160. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/client/models.py +0 -0
  161. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/client/runtime_client.py +0 -0
  162. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/client/transports.py +0 -0
  163. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/config.py +0 -0
  164. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/env.py +0 -0
  165. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/main.py +0 -0
  166. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/model_catalog.py +0 -0
  167. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/paths.py +0 -0
  168. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/print_mode.py +0 -0
  169. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/server/__init__.py +0 -0
  170. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/server/app.py +0 -0
  171. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/server/auth.py +0 -0
  172. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/server/capability_manager.py +0 -0
  173. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/server/prompt.py +0 -0
  174. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/server/prompt_registry.py +0 -0
  175. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/server/runtime_events.py +0 -0
  176. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/server/session_hydrator.py +0 -0
  177. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/server/session_persistence.py +0 -0
  178. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/server/turn_coordinator.py +0 -0
  179. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/server/utils.py +0 -0
  180. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/server/websocket.py +0 -0
  181. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/server/worker_manager.py +0 -0
  182. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/__init__.py +0 -0
  183. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/app.py +0 -0
  184. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/auth_flow.py +0 -0
  185. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/capabilities_manager.py +0 -0
  186. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/command_dispatcher.py +0 -0
  187. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/commands.py +0 -0
  188. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/connection.py +0 -0
  189. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/dreadnode.tcss +0 -0
  190. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/error_handler.py +0 -0
  191. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/model_manager.py +0 -0
  192. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/model_variants.py +0 -0
  193. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/profile_manager.py +0 -0
  194. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/runtime_cache.py +0 -0
  195. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/screen_router.py +0 -0
  196. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/screens/__init__.py +0 -0
  197. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/screens/auth.py +0 -0
  198. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/screens/base.py +0 -0
  199. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/screens/capabilities.py +0 -0
  200. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/screens/capability_docs.py +0 -0
  201. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/screens/connection_error.py +0 -0
  202. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/screens/console.py +0 -0
  203. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/screens/environments.py +0 -0
  204. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/screens/evaluations.py +0 -0
  205. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/screens/models.py +0 -0
  206. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/screens/raw_spans.py +0 -0
  207. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/screens/runtimes.py +0 -0
  208. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/screens/sandboxes.py +0 -0
  209. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/screens/secrets.py +0 -0
  210. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/screens/services.py +0 -0
  211. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/screens/sessions.py +0 -0
  212. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/screens/theme_showcase.py +0 -0
  213. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/screens/traces.py +0 -0
  214. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/screens/workspaces.py +0 -0
  215. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/sessions_manager.py +0 -0
  216. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/spans_reader.py +0 -0
  217. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/status_messages.py +0 -0
  218. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/theme.py +0 -0
  219. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/turn_coordinator.py +0 -0
  220. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/turn_lifecycle.py +0 -0
  221. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/turn_reducer.py +0 -0
  222. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/turn_state_phase.py +0 -0
  223. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/update_check.py +0 -0
  224. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/widgets/__init__.py +0 -0
  225. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/widgets/agent_dialog.py +0 -0
  226. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/widgets/agent_suggester.py +0 -0
  227. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/widgets/composer.py +0 -0
  228. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/widgets/confirm_modal.py +0 -0
  229. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/widgets/context_bar.py +0 -0
  230. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/widgets/conversation.py +0 -0
  231. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/widgets/flash.py +0 -0
  232. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/widgets/header_bar.py +0 -0
  233. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/widgets/help_panel.py +0 -0
  234. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/widgets/human_prompt.py +0 -0
  235. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/widgets/mention_overlay.py +0 -0
  236. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/widgets/message_queue.py +0 -0
  237. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/widgets/new_messages_pill.py +0 -0
  238. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/widgets/overlay_mixin.py +0 -0
  239. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/widgets/permission_prompt.py +0 -0
  240. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/widgets/profile_dialog.py +0 -0
  241. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/widgets/prompt_info.py +0 -0
  242. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/widgets/rewind_picker.py +0 -0
  243. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/widgets/session_sidebar.py +0 -0
  244. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/widgets/skills_dialog.py +0 -0
  245. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/widgets/slash_overlay.py +0 -0
  246. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/widgets/status_bar.py +0 -0
  247. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/widgets/throbber.py +0 -0
  248. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/widgets/tool.py +0 -0
  249. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/widgets/tool_progress.py +0 -0
  250. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/widgets/tools_dialog.py +0 -0
  251. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/widgets/welcome.py +0 -0
  252. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/widgets/whoami.py +0 -0
  253. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/app/tui/wire_events.py +0 -0
  254. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/__init__.py +0 -0
  255. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/MAINTAINING.md +0 -0
  256. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/capability.yaml +0 -0
  257. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/SKILL.md +0 -0
  258. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/capability-improvement.md +0 -0
  259. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/methodology-grounding.md +0 -0
  260. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/prior-art-audit.md +0 -0
  261. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/promoting-capabilities.md +0 -0
  262. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/quality-bar.md +0 -0
  263. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/INDEX.md +0 -0
  264. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/agents.md +0 -0
  265. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/dependencies-and-checks.md +0 -0
  266. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/env-vars.md +0 -0
  267. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/events.md +0 -0
  268. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/flags.md +0 -0
  269. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/hooks.md +0 -0
  270. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/installing.md +0 -0
  271. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/manifest.md +0 -0
  272. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/mcp-servers.md +0 -0
  273. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/overview.md +0 -0
  274. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/policies.md +0 -0
  275. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/publishing.md +0 -0
  276. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/quickstart.md +0 -0
  277. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/skills.md +0 -0
  278. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/tools.md +0 -0
  279. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/workers-reference.md +0 -0
  280. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/workers.md +0 -0
  281. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/writing-skills.md +0 -0
  282. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/sdk/agents.md +0 -0
  283. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/sdk/capabilities.md +0 -0
  284. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/tui/default-tools.md +0 -0
  285. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references-and-depth.md +0 -0
  286. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/runtime-default-capability.md +0 -0
  287. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/SKILL.md +0 -0
  288. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/INDEX.md +0 -0
  289. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/airt.md +0 -0
  290. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/capability.md +0 -0
  291. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/dataset.md +0 -0
  292. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/env.md +0 -0
  293. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/evaluation.md +0 -0
  294. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/inference-model.md +0 -0
  295. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/main.md +0 -0
  296. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/model.md +0 -0
  297. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/optimize.md +0 -0
  298. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/overview.md +0 -0
  299. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/runtime.md +0 -0
  300. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/sandbox.md +0 -0
  301. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/secret.md +0 -0
  302. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/task.md +0 -0
  303. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/train.md +0 -0
  304. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/worlds.md +0 -0
  305. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/getting-started/authentication.md +0 -0
  306. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/SKILL.md +0 -0
  307. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/INDEX.md +0 -0
  308. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/capabilities/installing.md +0 -0
  309. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/capabilities/overview.md +0 -0
  310. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/getting-started/authentication.md +0 -0
  311. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/getting-started/overview.md +0 -0
  312. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/getting-started/quickstart.md +0 -0
  313. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/chat-models.md +0 -0
  314. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/credits.md +0 -0
  315. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/organizations.md +0 -0
  316. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/overview.md +0 -0
  317. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/projects.md +0 -0
  318. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/secrets.md +0 -0
  319. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/users.md +0 -0
  320. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/workspaces.md +0 -0
  321. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/runtimes/configuration.md +0 -0
  322. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/runtimes/managing.md +0 -0
  323. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/runtimes/manifest-reference.md +0 -0
  324. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/runtimes/overview.md +0 -0
  325. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/runtimes/quickstart.md +0 -0
  326. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/runtimes/serve.md +0 -0
  327. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/sandboxes/environment-lifecycle.md +0 -0
  328. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/sandboxes/inspecting.md +0 -0
  329. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/sandboxes/overview.md +0 -0
  330. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/sandboxes/runtime-limits.md +0 -0
  331. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/getting-started/SKILL.md +0 -0
  332. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/dreadnode/skills/research-capabilities/SKILL.md +0 -0
  333. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/self-improvement/.gitignore +0 -0
  334. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/self-improvement/capability.yaml +0 -0
  335. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/self-improvement/hooks/__init__.py +0 -0
  336. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/self-improvement/hooks/observer.py +0 -0
  337. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/self-improvement/self_improvement_lib/__init__.py +0 -0
  338. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/self-improvement/self_improvement_lib/classifier.py +0 -0
  339. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/self-improvement/self_improvement_lib/reflector_goal.py +0 -0
  340. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/self-improvement/self_improvement_lib/skill_io.py +0 -0
  341. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/self-improvement/skills-promoted/.gitkeep +0 -0
  342. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/self-improvement/skills-proposed/.gitkeep +0 -0
  343. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/self-improvement/tools/__init__.py +0 -0
  344. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/self-improvement/tools/reflector.py +0 -0
  345. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/builtin_capabilities/self-improvement/tools/skill_stats.py +0 -0
  346. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/capabilities/__init__.py +0 -0
  347. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/capabilities/capability.py +0 -0
  348. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/capabilities/flags.py +0 -0
  349. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/capabilities/install.py +0 -0
  350. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/capabilities/loader.py +0 -0
  351. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/capabilities/sync.py +0 -0
  352. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/capabilities/tool_rules.py +0 -0
  353. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/capabilities/types.py +0 -0
  354. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/capabilities/worker.py +0 -0
  355. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/capabilities/worker_runner.py +0 -0
  356. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/core/__init__.py +0 -0
  357. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/core/conditions.py +0 -0
  358. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/core/discovery.py +0 -0
  359. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/core/environment.py +0 -0
  360. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/core/exceptions.py +0 -0
  361. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/core/execution.py +0 -0
  362. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/core/hook.py +0 -0
  363. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/core/judge.py +0 -0
  364. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/core/load.py +0 -0
  365. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/core/log.py +0 -0
  366. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/core/meta/__init__.py +0 -0
  367. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/core/meta/config.py +0 -0
  368. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/core/meta/context.py +0 -0
  369. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/core/meta/hydrate.py +0 -0
  370. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/core/meta/introspect.py +0 -0
  371. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/core/metric.py +0 -0
  372. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/core/object.py +0 -0
  373. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/core/scorer.py +0 -0
  374. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/core/serialization.py +0 -0
  375. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/core/stopping.py +0 -0
  376. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/core/task.py +0 -0
  377. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/core/templating.py +0 -0
  378. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/core/transforms.py +0 -0
  379. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/core/types/__init__.py +0 -0
  380. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/core/types/audio.py +0 -0
  381. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/core/types/base.py +0 -0
  382. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/core/types/common.py +0 -0
  383. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/core/types/image.py +0 -0
  384. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/core/types/object_3d.py +0 -0
  385. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/core/types/table.py +0 -0
  386. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/core/types/text.py +0 -0
  387. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/core/types/video.py +0 -0
  388. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/core/util.py +0 -0
  389. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/datasets/__init__.py +0 -0
  390. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/datasets/dataset.py +0 -0
  391. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/datasets/hf.py +0 -0
  392. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/datasets/local.py +0 -0
  393. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/evaluations/__init__.py +0 -0
  394. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/evaluations/console.py +0 -0
  395. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/evaluations/evaluation.py +0 -0
  396. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/evaluations/events.py +0 -0
  397. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/evaluations/format.py +0 -0
  398. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/evaluations/result.py +0 -0
  399. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/evaluations/sample.py +0 -0
  400. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/generators/__init__.py +0 -0
  401. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/generators/caching.py +0 -0
  402. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/generators/chat.py +0 -0
  403. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/generators/data.py +0 -0
  404. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/generators/exceptions.py +0 -0
  405. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/generators/generator/__init__.py +0 -0
  406. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/generators/generator/base.py +0 -0
  407. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/generators/generator/http.py +0 -0
  408. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/generators/generator/transformers_.py +0 -0
  409. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/generators/generator/vllm_.py +0 -0
  410. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/generators/models.py +0 -0
  411. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/generators/parsing.py +0 -0
  412. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/generators/tokenizer/__init__.py +0 -0
  413. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/generators/tokenizer/base.py +0 -0
  414. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/generators/tokenizer/transformers_.py +0 -0
  415. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/generators/utils.py +0 -0
  416. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/judges/__init__.py +0 -0
  417. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/judges/outcome.py +0 -0
  418. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/judges/trajectory.py +0 -0
  419. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/judges/trajectory_tools.py +0 -0
  420. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/models/__init__.py +0 -0
  421. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/models/hf.py +0 -0
  422. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/models/local.py +0 -0
  423. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/models/model.py +0 -0
  424. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/optimization/__init__.py +0 -0
  425. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/optimization/adapters/__init__.py +0 -0
  426. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/optimization/adapters/_env_eval.py +0 -0
  427. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/optimization/adapters/agent.py +0 -0
  428. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/optimization/adapters/env.py +0 -0
  429. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/optimization/adapters/runtime.py +0 -0
  430. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/optimization/adapters/stack.py +0 -0
  431. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/optimization/api.py +0 -0
  432. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/optimization/backends/__init__.py +0 -0
  433. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/optimization/backends/base.py +0 -0
  434. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/optimization/backends/gepa.py +0 -0
  435. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/optimization/collectors.py +0 -0
  436. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/optimization/config.py +0 -0
  437. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/optimization/console.py +0 -0
  438. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/optimization/events.py +0 -0
  439. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/optimization/format.py +0 -0
  440. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/optimization/jobs.py +0 -0
  441. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/optimization/result.py +0 -0
  442. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/optimization/sampler.py +0 -0
  443. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/optimization/sampling.py +0 -0
  444. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/optimization/search.py +0 -0
  445. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/optimization/stopping.py +0 -0
  446. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/optimization/study.py +0 -0
  447. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/optimization/trial.py +0 -0
  448. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/packaging/__init__.py +0 -0
  449. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/packaging/loader.py +0 -0
  450. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/packaging/manifest.py +0 -0
  451. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/packaging/oci.py +0 -0
  452. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/packaging/package.py +0 -0
  453. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/policies/__init__.py +0 -0
  454. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/policies/guard.py +0 -0
  455. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/policies/rubrics/process/default.yaml +0 -0
  456. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/py.typed +0 -0
  457. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/samplers/__init__.py +0 -0
  458. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/samplers/boundary.py +0 -0
  459. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/samplers/fuzzing.py +0 -0
  460. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/samplers/graph.py +0 -0
  461. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/samplers/grid.py +0 -0
  462. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/samplers/image.py +0 -0
  463. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/samplers/mapelites.py +0 -0
  464. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/samplers/optuna.py +0 -0
  465. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/samplers/random.py +0 -0
  466. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/samplers/registry.py +0 -0
  467. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/samplers/strategy.py +0 -0
  468. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/scorers/__init__.py +0 -0
  469. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/scorers/advanced_jailbreak_detection.py +0 -0
  470. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/scorers/agent_security.py +0 -0
  471. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/scorers/agentic.py +0 -0
  472. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/scorers/agentic_workflow.py +0 -0
  473. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/scorers/attack_outcome.py +0 -0
  474. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/scorers/classification.py +0 -0
  475. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/scorers/consistency.py +0 -0
  476. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/scorers/contains.py +0 -0
  477. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/scorers/cosine_sim.py +0 -0
  478. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/scorers/credentials.py +0 -0
  479. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/scorers/crucible.py +0 -0
  480. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/scorers/documentation_security.py +0 -0
  481. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/scorers/exfiltration_detection.py +0 -0
  482. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/scorers/format.py +0 -0
  483. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/scorers/harm.py +0 -0
  484. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/scorers/ide_security.py +0 -0
  485. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/scorers/image.py +0 -0
  486. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/scorers/json.py +0 -0
  487. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/scorers/judge.py +0 -0
  488. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/scorers/judge_ensemble.py +0 -0
  489. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/scorers/length.py +0 -0
  490. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/scorers/lexical.py +0 -0
  491. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/scorers/mcp_security.py +0 -0
  492. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/scorers/memorization.py +0 -0
  493. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/scorers/multi_agent_security.py +0 -0
  494. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/scorers/pii.py +0 -0
  495. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/scorers/prompt_leak.py +0 -0
  496. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/scorers/readability.py +0 -0
  497. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/scorers/reasoning_security.py +0 -0
  498. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/scorers/sentiment.py +0 -0
  499. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/scorers/similarity.py +0 -0
  500. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/scorers/structural_detection.py +0 -0
  501. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/scorers/supply_chain_detection.py +0 -0
  502. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/storage/__init__.py +0 -0
  503. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/storage/providers.py +0 -0
  504. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/storage/session_store.py +0 -0
  505. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/storage/storage.py +0 -0
  506. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/tools/__init__.py +0 -0
  507. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/tools/_ripgrep.py +0 -0
  508. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/tools/apply_patch.py +0 -0
  509. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/tools/dreadnode_cli.py +0 -0
  510. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/tools/editing.py +0 -0
  511. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/tools/execute.py +0 -0
  512. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/tools/fetch.py +0 -0
  513. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/tools/glob.py +0 -0
  514. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/tools/grep.py +0 -0
  515. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/tools/interaction.py +0 -0
  516. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/tools/ls.py +0 -0
  517. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/tools/memory.py +0 -0
  518. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/tools/report.py +0 -0
  519. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/tools/task.py +0 -0
  520. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/tools/think.py +0 -0
  521. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/tools/todo.py +0 -0
  522. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/tools/trajectory_search.py +0 -0
  523. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/tools/web_extract.py +0 -0
  524. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/tools/web_search.py +0 -0
  525. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/tools/write.py +0 -0
  526. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/tracing/__init__.py +0 -0
  527. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/tracing/constants.py +0 -0
  528. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/tracing/convert.py +0 -0
  529. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/tracing/exporter.py +0 -0
  530. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/tracing/exporters.py +0 -0
  531. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/tracing/span.py +0 -0
  532. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/tracing/spans.py +0 -0
  533. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/tracing/trace_converter.py +0 -0
  534. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/__init__.py +0 -0
  535. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/_progress.py +0 -0
  536. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/base.py +0 -0
  537. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/dpo.py +0 -0
  538. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/env_rollouts.py +0 -0
  539. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/etl/__init__.py +0 -0
  540. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/etl/_common.py +0 -0
  541. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/etl/rl.py +0 -0
  542. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/etl/sft.py +0 -0
  543. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/etl/worlds.py +0 -0
  544. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/events.py +0 -0
  545. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/grpo.py +0 -0
  546. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/jobs.py +0 -0
  547. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/models.py +0 -0
  548. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/ppo.py +0 -0
  549. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/prime.py +0 -0
  550. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/ray/__init__.py +0 -0
  551. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/ray/async_trainer.py +0 -0
  552. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/ray/config.py +0 -0
  553. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/ray/coordinator.py +0 -0
  554. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/ray/distributed.py +0 -0
  555. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/ray/dpo.py +0 -0
  556. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/ray/experience.py +0 -0
  557. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/ray/fsdp2_learner.py +0 -0
  558. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/ray/inference.py +0 -0
  559. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/ray/learner.py +0 -0
  560. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/ray/multi_turn.py +0 -0
  561. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/ray/ppo.py +0 -0
  562. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/ray/reward_model.py +0 -0
  563. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/ray/rollout_env.py +0 -0
  564. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/ray/rollout_worker.py +0 -0
  565. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/ray/sft.py +0 -0
  566. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/ray/trainer.py +0 -0
  567. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/recipes.py +0 -0
  568. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/rewards/__init__.py +0 -0
  569. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/rewards/aggregator.py +0 -0
  570. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/rewards/functions.py +0 -0
  571. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/rewards/scorer_bridge.py +0 -0
  572. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/rewards/shaping.py +0 -0
  573. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/rewards/types.py +0 -0
  574. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/rollouts/__init__.py +0 -0
  575. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/rollouts/adapters.py +0 -0
  576. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/rollouts/agent_rollout.py +0 -0
  577. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/rollouts/orchestrator.py +0 -0
  578. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/rollouts/types.py +0 -0
  579. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/rollouts/worlds.py +0 -0
  580. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/serving/__init__.py +0 -0
  581. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/serving/vllm_client.py +0 -0
  582. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/sft.py +0 -0
  583. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/tinker/__init__.py +0 -0
  584. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/tinker/config.py +0 -0
  585. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/tinker/data.py +0 -0
  586. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/tinker/renderer.py +0 -0
  587. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/tinker/rl.py +0 -0
  588. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/tinker/trainer.py +0 -0
  589. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/tinker_sft.py +0 -0
  590. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/training/utils.py +0 -0
  591. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/transforms/__init__.py +0 -0
  592. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/transforms/advanced_jailbreak.py +0 -0
  593. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/transforms/adversarial_suffix.py +0 -0
  594. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/transforms/agent_skill.py +0 -0
  595. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/transforms/agentic_workflow.py +0 -0
  596. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/transforms/audio.py +0 -0
  597. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/transforms/backdoor_finetune.py +0 -0
  598. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/transforms/browser_agent_attacks.py +0 -0
  599. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/transforms/cipher.py +0 -0
  600. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/transforms/competitive_parity.py +0 -0
  601. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/transforms/constitutional.py +0 -0
  602. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/transforms/document.py +0 -0
  603. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/transforms/documentation_poison.py +0 -0
  604. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/transforms/encoding.py +0 -0
  605. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/transforms/exfiltration.py +0 -0
  606. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/transforms/flip_attack.py +0 -0
  607. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/transforms/guardrail_bypass.py +0 -0
  608. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/transforms/ide_injection.py +0 -0
  609. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/transforms/image.py +0 -0
  610. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/transforms/injection.py +0 -0
  611. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/transforms/json_tools.py +0 -0
  612. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/transforms/language.py +0 -0
  613. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/transforms/logic_bomb.py +0 -0
  614. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/transforms/mcp_attacks.py +0 -0
  615. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/transforms/multi_agent_attacks.py +0 -0
  616. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/transforms/multimodal_attacks.py +0 -0
  617. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/transforms/persuasion.py +0 -0
  618. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/transforms/perturbation.py +0 -0
  619. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/transforms/pii_extraction.py +0 -0
  620. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/transforms/pythonic_tools.py +0 -0
  621. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/transforms/rag_poisoning.py +0 -0
  622. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/transforms/reasoning_attacks.py +0 -0
  623. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/transforms/refine.py +0 -0
  624. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/transforms/response_steering.py +0 -0
  625. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/transforms/structural_exploits.py +0 -0
  626. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/transforms/stylistic.py +0 -0
  627. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/transforms/substitution.py +0 -0
  628. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/transforms/supply_chain.py +0 -0
  629. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/transforms/swap.py +0 -0
  630. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/transforms/system_prompt_extraction.py +0 -0
  631. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/transforms/text.py +0 -0
  632. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/transforms/video.py +0 -0
  633. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/transforms/xml_tools.py +0 -0
  634. {dreadnode-2.0.29 → dreadnode-2.0.30}/dreadnode/version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dreadnode
3
- Version: 2.0.29
3
+ Version: 2.0.30
4
4
  Summary: Dreadnode SDK
5
5
  Project-URL: Homepage, https://dreadnode.io
6
6
  Project-URL: Documentation, https://docs.dreadnode.io
@@ -155,6 +155,11 @@ class Assessment:
155
155
  self._tracing_enabled: bool = False
156
156
  self._auto_registered: bool = False
157
157
  self._context_token: contextvars.Token[Assessment | None] | None = None
158
+ # Terminal-failure latch. Once fail() runs, auto-finalization
159
+ # (_finalize/complete/atexit) must NOT flip the status back to
160
+ # "completed" — otherwise a failure caught inside the `async with`
161
+ # block is masked by the clean-exit auto-complete (ENG-6822).
162
+ self._failed: bool = False
158
163
 
159
164
  async def __aenter__(self) -> Assessment:
160
165
  self._context_token = _current_assessment.set(self)
@@ -507,7 +512,7 @@ class Assessment:
507
512
  return
508
513
 
509
514
  api, profile = ctx
510
- status = "completed" if self._attack_results else "failed"
515
+ status = "completed" if (self._attack_results and not self._failed) else "failed"
511
516
  with contextlib.suppress(Exception):
512
517
  api.update_airt_assessment(
513
518
  profile.org_key,
@@ -542,6 +547,11 @@ class Assessment:
542
547
  Returns:
543
548
  True if successfully marked, False otherwise.
544
549
  """
550
+ # A failed assessment is terminal — never auto-complete over it.
551
+ if self._failed:
552
+ logger.debug("Skipping complete(): assessment already marked as failed")
553
+ return False
554
+
545
555
  ctx = _get_platform_context_with_fallback()
546
556
  if ctx is None or self._assessment_id is None:
547
557
  return False
@@ -570,6 +580,10 @@ class Assessment:
570
580
  Returns:
571
581
  True if successfully marked, False otherwise.
572
582
  """
583
+ # Latch terminal failure first — even offline / before registration —
584
+ # so any later auto-finalization won't re-complete (ENG-6822).
585
+ self._failed = True
586
+
573
587
  ctx = _get_platform_context_with_fallback()
574
588
  if ctx is None or self._assessment_id is None:
575
589
  return False
@@ -881,6 +881,20 @@ def validate(
881
881
  smoke: t.Annotated[bool, cyclopts.Parameter(negative=())] = False,
882
882
  pull: t.Annotated[bool, cyclopts.Parameter(name="--pull", negative=())] = False,
883
883
  yes: t.Annotated[bool, cyclopts.Parameter(name="--yes", alias="-y", negative=())] = False,
884
+ env: t.Annotated[
885
+ list[str] | None,
886
+ cyclopts.Parameter(
887
+ name="--env",
888
+ alias="-e",
889
+ help=(
890
+ "Inject env into the challenge service at smoke time only "
891
+ "(KEY=VALUE for a literal, or bare KEY to forward the value from "
892
+ "your shell so secrets stay out of argv; repeatable). Scoped to "
893
+ "the challenge/task service -- does not reach solution.sh or verify."
894
+ ),
895
+ negative_iterable=(),
896
+ ),
897
+ ] = None,
884
898
  timeout: int | None = None,
885
899
  platform: PlatformArgs = PlatformArgs(),
886
900
  ) -> None:
@@ -905,6 +919,14 @@ def validate(
905
919
  ``outcome_judge`` has no mechanical half and is skipped.
906
920
  pull: Treat path as a published task ref and pull it for local validation.
907
921
  yes: Accept remote validation without prompting when path is not local.
922
+ env: Env to inject into the challenge service for the smoke run only
923
+ (``-e``/``--env``, repeatable). ``KEY=VALUE`` sets a literal; a bare
924
+ ``KEY`` forwards the value from ``os.environ`` so secrets never touch
925
+ argv. Merged into the ephemeral compose -- the on-disk compose is
926
+ untouched -- and overrides any same-named key the compose declares.
927
+ Targets the challenge/task service(s) only: it does NOT reach
928
+ solution.sh or verify, which run in a separate sandbox. Only
929
+ meaningful with ``--smoke``; ignored (with a warning) otherwise.
908
930
  timeout: Per-task wall-clock budget in seconds for smoke testing.
909
931
  When unset, falls back to the task's ``max_agent_timeout_sec`` or
910
932
  120 seconds if neither is declared.
@@ -912,6 +934,10 @@ def validate(
912
934
  if smoke:
913
935
  build = True
914
936
 
937
+ if env and not smoke:
938
+ print_warning("--env / -e only applies to --smoke; ignoring", indent=2)
939
+ env = None
940
+
915
941
  resolved = Path(path).resolve()
916
942
  if resolved.exists():
917
943
  _validate_local_task_path(
@@ -920,6 +946,7 @@ def validate(
920
946
  build=build,
921
947
  smoke=smoke,
922
948
  timeout=timeout,
949
+ service_env=env,
923
950
  )
924
951
  return
925
952
 
@@ -939,6 +966,7 @@ def validate(
939
966
  build=build,
940
967
  smoke=smoke,
941
968
  timeout=timeout,
969
+ service_env=env,
942
970
  )
943
971
 
944
972
 
@@ -949,6 +977,7 @@ def _validate_local_task_path(
949
977
  build: bool,
950
978
  smoke: bool,
951
979
  timeout: int | None,
980
+ service_env: list[str] | None = None,
952
981
  ) -> None:
953
982
  """Run validation against a local task directory or task tree."""
954
983
  from dreadnode.packaging.task_validation import (
@@ -997,7 +1026,7 @@ def _validate_local_task_path(
997
1026
  errs.append(ValidationIssue("error", "docker-build", summary))
998
1027
 
999
1028
  if smoke and not errs:
1000
- smoke_issues = _run_smoke_test(task_dir, timeout=timeout)
1029
+ smoke_issues = _run_smoke_test(task_dir, timeout=timeout, service_env=service_env)
1001
1030
  for issue in smoke_issues:
1002
1031
  if issue.level == "error":
1003
1032
  errs.append(issue)
@@ -1087,6 +1116,7 @@ def _validate_remote_task_ref(
1087
1116
  build: bool,
1088
1117
  smoke: bool,
1089
1118
  timeout: int | None = None,
1119
+ service_env: list[str] | None = None,
1090
1120
  ) -> None:
1091
1121
  dn = configured_dreadnode(platform)
1092
1122
  print_info(f"Pulling {ref.qualified_name}@{ref.version} for local validation")
@@ -1106,6 +1136,7 @@ def _validate_remote_task_ref(
1106
1136
  build=build,
1107
1137
  smoke=smoke,
1108
1138
  timeout=timeout,
1139
+ service_env=service_env,
1109
1140
  )
1110
1141
 
1111
1142
 
@@ -1815,13 +1846,75 @@ def _wipe_ephemeral_bind_mount_dirs(paths: list[Path]) -> None:
1815
1846
  path.mkdir(parents=True, exist_ok=True)
1816
1847
 
1817
1848
 
1818
- def _write_ephemeral_compose_file(original: Path, destination: Path) -> dict[str, list[int]]:
1849
+ def _parse_service_env(values: list[str] | None) -> dict[str, str]:
1850
+ """Parse repeatable smoke ``-e``/``--env`` flags into a ``{KEY: VALUE}`` map.
1851
+
1852
+ ``KEY=VALUE`` sets a literal value (split on the first ``=``). A bare ``KEY``
1853
+ forwards the value from ``os.environ`` so secrets stay out of argv, shell
1854
+ history, and ``ps``. A bare key whose variable is unset is an error -- you
1855
+ asked to forward it, but there is nothing to forward, so fail loud rather
1856
+ than silently inject an empty string.
1857
+ """
1858
+ if not values:
1859
+ return {}
1860
+ import os
1861
+
1862
+ out: dict[str, str] = {}
1863
+ for raw in values:
1864
+ key, sep, value = raw.partition("=")
1865
+ key = key.strip()
1866
+ if not key:
1867
+ raise ValueError(f"--env expects KEY or KEY=VALUE, got: {raw!r}")
1868
+ if sep:
1869
+ out[key] = value
1870
+ elif key in os.environ:
1871
+ out[key] = os.environ[key]
1872
+ else:
1873
+ raise ValueError(
1874
+ f"--env {key}: no value supplied and {key} is not set in the environment"
1875
+ )
1876
+ return out
1877
+
1878
+
1879
+ def _normalize_compose_env(raw: t.Any) -> dict[str, t.Any]:
1880
+ """Normalize a compose ``environment`` block to map form.
1881
+
1882
+ Compose accepts either a list (``["K=v", "BARE"]``) or a map
1883
+ (``{K: v}``). List entries are split on the first ``=``; a bare list entry
1884
+ (host pass-through) becomes ``{KEY: None}``. Anything else yields an empty
1885
+ map so callers can merge unconditionally.
1886
+ """
1887
+ if isinstance(raw, dict):
1888
+ return dict(raw)
1889
+ if isinstance(raw, list):
1890
+ out: dict[str, t.Any] = {}
1891
+ for entry in raw:
1892
+ if not isinstance(entry, str):
1893
+ continue
1894
+ key, sep, value = entry.partition("=")
1895
+ out[key] = value if sep else None
1896
+ return out
1897
+ return {}
1898
+
1899
+
1900
+ def _write_ephemeral_compose_file(
1901
+ original: Path,
1902
+ destination: Path,
1903
+ *,
1904
+ inject_env: dict[str, str] | None = None,
1905
+ ) -> dict[str, list[int]]:
1819
1906
  """Rewrite ``original`` so every service's ports use random host ports.
1820
1907
 
1821
1908
  Docker compose short-form ``"3000"`` (container port only) assigns a
1822
1909
  random host port at ``up`` time, which we discover afterwards via
1823
1910
  ``docker compose port``. Returns ``{service: [container_port, ...]}`` so
1824
1911
  the caller knows which ports to query.
1912
+
1913
+ When ``inject_env`` is given, those entries are merged into every service's
1914
+ ``environment`` block (normalized to map form first), overriding any
1915
+ same-named key the compose declares. This is the smoke-time challenge-env
1916
+ injection (``dn task validate --smoke -e KEY=VALUE``): non-destructive, the
1917
+ on-disk compose is never touched -- the same seam where ports are mutated.
1825
1918
  """
1826
1919
  import yaml
1827
1920
 
@@ -1838,6 +1931,10 @@ def _write_ephemeral_compose_file(original: Path, destination: Path) -> dict[str
1838
1931
  for svc_name, svc_config in services.items():
1839
1932
  if not isinstance(svc_config, dict):
1840
1933
  continue
1934
+ if inject_env:
1935
+ merged = _normalize_compose_env(svc_config.get("environment"))
1936
+ merged.update(inject_env)
1937
+ svc_config["environment"] = merged
1841
1938
  raw_ports = svc_config.get("ports")
1842
1939
  if not isinstance(raw_ports, list) or not raw_ports:
1843
1940
  continue
@@ -2112,7 +2209,12 @@ def _resolve_smoke_timeout(raw: dict[str, t.Any], explicit: int | None) -> int:
2112
2209
  return _DEFAULT_SMOKE_TIMEOUT
2113
2210
 
2114
2211
 
2115
- def _run_smoke_test(task_dir: Path, *, timeout: int | None = None) -> list[ValidationIssue]:
2212
+ def _run_smoke_test(
2213
+ task_dir: Path,
2214
+ *,
2215
+ timeout: int | None = None,
2216
+ service_env: list[str] | None = None,
2217
+ ) -> list[ValidationIssue]:
2116
2218
  """Run the v1 smoke lifecycle for a single task directory.
2117
2219
 
2118
2220
  Lifecycle:
@@ -2160,6 +2262,14 @@ def _run_smoke_test(task_dir: Path, *, timeout: int | None = None) -> list[Valid
2160
2262
 
2161
2263
  issues: list[ValidationIssue] = []
2162
2264
 
2265
+ # Challenge-service env to merge into the ephemeral compose (smoke only).
2266
+ # Parse up front so a bad/unset bare key fails loud before any docker work.
2267
+ try:
2268
+ injected_service_env = _parse_service_env(service_env)
2269
+ except ValueError as exc:
2270
+ issues.append(ValidationIssue("error", "smoke", str(exc)))
2271
+ return issues
2272
+
2163
2273
  raw = yaml.safe_load((task_dir / "task.yaml").read_text())
2164
2274
  timeout = _resolve_smoke_timeout(raw, timeout)
2165
2275
  verification = raw.get("verification") or {}
@@ -2250,6 +2360,15 @@ def _run_smoke_test(task_dir: Path, *, timeout: int | None = None) -> list[Valid
2250
2360
  compose_path = _find_compose_file(task_dir)
2251
2361
  has_compose = compose_path is not None
2252
2362
 
2363
+ if injected_service_env and not has_compose:
2364
+ issues.append(
2365
+ ValidationIssue(
2366
+ "warning",
2367
+ "smoke",
2368
+ "-e/--env was given but this task has no compose service to inject into",
2369
+ )
2370
+ )
2371
+
2253
2372
  # Two smoke contexts are built after compose is up:
2254
2373
  # - host_env / host_template_vars: service URLs using the randomly
2255
2374
  # assigned host ports. Used for scripts that run on the host.
@@ -2338,7 +2457,11 @@ def _run_smoke_test(task_dir: Path, *, timeout: int | None = None) -> list[Valid
2338
2457
  prefix=f"{task_dir.name}-smoke-compose-"
2339
2458
  )
2340
2459
  smoke_compose_file = Path(smoke_compose_workspace.name) / compose_path.name
2341
- declared_host_ports = _write_ephemeral_compose_file(compose_path, smoke_compose_file)
2460
+ declared_host_ports = _write_ephemeral_compose_file(
2461
+ compose_path,
2462
+ smoke_compose_file,
2463
+ inject_env=injected_service_env or None,
2464
+ )
2342
2465
 
2343
2466
  # Clear smoke-owned ephemeral bind-mount dirs (e.g. ./.submission)
2344
2467
  # before compose up so a prior run's leftover state can't poison
@@ -108,18 +108,13 @@ def validate_model_environment(config: TurnModelConfig) -> str | None:
108
108
 
109
109
  def build_turn_generator(config: TurnModelConfig) -> "str | Generator":
110
110
  """Build the effective generator input for a turn or compaction request."""
111
- effective_model: str | Generator = config.generator_model
112
111
  if not config.is_platform_proxy:
113
- return effective_model
112
+ return config.generator_model
114
113
 
115
- from dreadnode.generators.generator import GenerateParams, get_generator
114
+ from dreadnode.generators.proxy import build_proxy_generator
116
115
 
117
- generator = get_generator(
116
+ return build_proxy_generator(
118
117
  config.generator_model,
119
- params=GenerateParams(
120
- api_base=config.api_base,
121
- extra={"custom_llm_provider": "litellm_proxy"},
122
- ),
118
+ api_base=config.api_base,
119
+ api_key=config.api_key,
123
120
  )
124
- generator.api_key = config.api_key
125
- return generator
@@ -208,7 +208,7 @@ def _get_result_text(res: t.Any) -> str:
208
208
  if isinstance(res, list):
209
209
  # Multimodal content-part lists (e.g. a ``read`` image result is a text
210
210
  # caption + an image part). Pull text out of each part and skip image/
211
- # audio parts, whose repr would otherwise bloat or corrupt the summary.
211
+ # video / audio parts, whose repr would otherwise bloat or corrupt the summary.
212
212
  parts: list[str] = []
213
213
  for x in res:
214
214
  if isinstance(x, dict):
@@ -218,7 +218,7 @@ def _get_result_text(res: t.Any) -> str:
218
218
  if isinstance(text, str):
219
219
  parts.append(text)
220
220
  continue
221
- if getattr(x, "type", None) in ("image_url", "input_audio"):
221
+ if getattr(x, "type", None) in ("image_url", "file", "input_audio"):
222
222
  continue
223
223
  parts.append(str(x))
224
224
  return "\n".join(p for p in parts if p)
@@ -237,9 +237,9 @@ def _summarize_read(_name: str, _args: dict[str, t.Any], result: t.Any) -> str |
237
237
  return None
238
238
 
239
239
  head = text.splitlines()[0] if text else ""
240
- # Image reads return a "Read image · <fmt> · <size>" caption (the path is
241
- # already shown in the call label, so it is intentionally not repeated).
242
- if head.startswith("Read image"):
240
+ # Image/video reads return a "Read <media> · <fmt> · <size>" caption (the
241
+ # path is already shown in the call label, so it is intentionally not repeated).
242
+ if head.startswith(("Read image", "Read video")):
243
243
  return head
244
244
  if head.startswith("PDF: "):
245
245
  return f"PDF: {head.removeprefix('PDF: ').rsplit('/', 1)[-1]}."
@@ -60,6 +60,8 @@ You are running in an isolated runtime. You can freely modify files and run comm
60
60
 
61
61
  Use bash for system and CLI commands. Use python for SDK inspection, quick scripting, and data analysis. If available, use memory to track key platform context and decisions across tool calls; use todo to track multi-step work; use think for complex reasoning without acting; use report to persist structured deliverables; use session_search to recover earlier messages from the current session. Tool availability depends on the active capability and runtime.
62
62
 
63
+ When the user provides media files or URLs to media files (images, videos, audio), use the `read` tool to load them. `read` returns proper multimodal content parts that the model can see or hear. Do not use `web_extract` or `fetch` for media files — those return raw bytes or text, not model-viewable multimodal content. For local media paths, use `read` as well.
64
+
63
65
  Capabilities add domain-specific agents, tools, and prompts. When a capability is active, let that capability own its specialized domain behavior instead of re-creating it in the core runtime agent.
64
66
 
65
67
  Persist results: traces are sent automatically, use dreadnode dataset publish to save data, dreadnode model push for models, and /export for conversation transcripts.
@@ -18,6 +18,7 @@ Settings is the app’s entry point for organization and user configuration. It
18
18
  | Workspaces | workspace creation and sharing | where should work happen and who gets access? | [Workspaces](./workspaces.md) |
19
19
  | Secrets | personal provider credentials | which keys do I want available for my runs and evaluations? | [Secrets](./secrets.md) |
20
20
  | Chat Models | chat UI model availability | which inference models should appear in my assistant picker? | [Chat models](./chat-models.md) |
21
+ | Preferences | user notification and marketing controls | which account-level communication preferences should I keep? | this page |
21
22
  | Billing | SaaS credits and payment controls | how do we pay for usage and keep workloads running? | [Credits](./credits.md) |
22
23
 
23
24
  ## What lives in settings
@@ -29,20 +30,22 @@ Settings is the app’s entry point for organization and user configuration. It
29
30
  | Workspaces | workspace creation, sharing, and per-workspace access management |
30
31
  | Secrets | provider API keys and custom environment variables |
31
32
  | Chat Models | your own BYOK model additions on top of the always-available Dreadnode models |
33
+ | Preferences | desktop notification toggles and marketing email subscription (`Dreadnode Updates`) |
32
34
  | Billing | credits, auto-refill, transactions, and usage in SaaS mode |
33
35
 
34
36
  The settings shell also surfaces an invite banner when an organization appears to be solo and the current user can manage members. In the app, that banner uses the `Invite Team` action to send you directly into membership management.
35
37
 
36
38
  ## Common operator tasks
37
39
 
38
- | If you need to… | Go to | Why |
39
- | ----------------------------------------------------------- | ------------- | ----------------------------------------------------------------- |
40
- | rename the org or review org-level limits | `General` | this is the top-level org metadata surface |
41
- | invite coworkers and adjust roles | `Members` | org membership and permission changes happen here |
42
- | create a shared delivery area for a team or engagement | `Workspaces` | workspace creation and access live here |
43
- | add your own provider key for future runs | `Secrets` | secrets are user-owned even though they are managed from settings |
44
- | decide which chat models appear in your chat UI | `Chat Models` | this is a user preference surface, not the artifact registry |
45
- | configure payment methods, auto-refill, or usage guardrails | `Billing` | this is the SaaS billing and credits surface |
40
+ | If you need to… | Go to | Why |
41
+ | ------------------------------------------------------------ | ------------- | ----------------------------------------------------------------- |
42
+ | rename the org or review org-level limits | `General` | this is the top-level org metadata surface |
43
+ | invite coworkers and adjust roles | `Members` | org membership and permission changes happen here |
44
+ | create a shared delivery area for a team or engagement | `Workspaces` | workspace creation and access live here |
45
+ | add your own provider key for future runs | `Secrets` | secrets are user-owned even though they are managed from settings |
46
+ | decide which chat models appear in your chat UI | `Chat Models` | this is a user preference surface, not the artifact registry |
47
+ | subscribe or unsubscribe from product-update marketing email | `Preferences` | this controls `Dreadnode Updates` only, not transactional email |
48
+ | configure payment methods, auto-refill, or usage guardrails | `Billing` | this is the SaaS billing and credits surface |
46
49
 
47
50
  ## Platform admin (runtime LiteLLM controls)
48
51
 
@@ -50,6 +53,8 @@ The settings shell also surfaces an invite banner when an organization appears t
50
53
 
51
54
  * `Admin → Credentials` rotates named LiteLLM provider credentials at runtime.
52
55
  * `Admin → Model Deployments` manages deployment rows and credential assignment for load balancing / routing changes. Drag rows to set the order hosted models appear in TUI and chat model lists — changes apply to new sessions within about a minute.
56
+ * `Admin → Diagnostics` shows read-only LiteLLM liveliness and running-version status.
57
+ * `Admin → Security` manages signup abuse controls (rolling signup-per-IP limits and CIDR deny rules) plus disposable email-domain override entries.
53
58
 
54
59
  These controls are `PLATFORM_ADMIN`-scoped and are separate from user-owned `Secrets` in settings.
55
60
 
@@ -116,6 +121,14 @@ Use `Secrets` when you are storing credentials that you personally want to injec
116
121
 
117
122
  Use `Chat Models` when you are adding your own BYOK models to the interactive assistant UI — Dreadnode-hosted models are available by default. See [Chat models](./chat-models.md) for the full mechanic, including which provider key each BYOK model needs.
118
123
 
124
+ ### Preferences
125
+
126
+ Use `Preferences` when you are managing account-level communication controls.
127
+
128
+ * toggle desktop notifications for long-running task completion alerts
129
+ * subscribe or unsubscribe from the `Dreadnode Updates` marketing list
130
+ * note that transactional emails (verification, password reset, operational notices) are independent from marketing preference
131
+
119
132
  ### Billing
120
133
 
121
134
  Use `Billing` when you are managing credits-backed usage in SaaS deployments.
@@ -134,14 +147,15 @@ Use `Billing` when you are managing credits-backed usage in SaaS deployments.
134
147
 
135
148
  ## Permission guide
136
149
 
137
- | Section | Scope | Safe default assumption |
138
- | ----------- | ---------------------------------- | ----------------------------------------------------------------- |
139
- | General | organization | org-admin action |
140
- | Members | organization | org-admin action with invite and role management |
141
- | Workspaces | organization plus workspace access | org-level creation plus workspace-sharing controls |
142
- | Secrets | user | each user manages their own credentials |
143
- | Chat Models | user | treat as a per-user model-picker preference, not a registry write |
144
- | Billing | organization, SaaS only | owner-level billing action |
150
+ | Section | Scope | Safe default assumption |
151
+ | ----------- | ---------------------------------- | ------------------------------------------------------------------ |
152
+ | General | organization | org-admin action |
153
+ | Members | organization | org-admin action with invite and role management |
154
+ | Workspaces | organization plus workspace access | org-level creation plus workspace-sharing controls |
155
+ | Secrets | user | each user manages their own credentials |
156
+ | Chat Models | user | treat as a per-user model-picker preference, not a registry write |
157
+ | Preferences | user | per-user communication preferences for notifications and marketing |
158
+ | Billing | organization, SaaS only | owner-level billing action |
145
159
 
146
160
  ## SaaS versus Enterprise
147
161
 
@@ -8,6 +8,7 @@ import warnings
8
8
  from loguru import logger
9
9
 
10
10
  from dreadnode.agents.tools import FunctionDefinition, ToolDefinition
11
+ from dreadnode.app.model_catalog import infer_provider
11
12
  from dreadnode.generators.exceptions import GeneratorWarning, ProcessingError
12
13
  from dreadnode.generators.generator.base import (
13
14
  Fixup,
@@ -21,6 +22,7 @@ from dreadnode.generators.generator.base import (
21
22
  with_fixups,
22
23
  )
23
24
  from dreadnode.generators.message import (
25
+ CompatibilityFlag,
24
26
  ContentAudioInput,
25
27
  ContentImageUrl,
26
28
  ContentText,
@@ -341,6 +343,16 @@ g_fixups = [
341
343
  vertex_image_pattern = re.compile(r"(data:[\w/]+?;base64,[A-Za-z0-9+/=]+)")
342
344
 
343
345
 
346
+ def _compatibility_flags_for_model(model: str) -> set[CompatibilityFlag]:
347
+ """Return message serialization flags needed by LiteLLM provider adapters."""
348
+ normalized = model.lower()
349
+ if infer_provider(model) == "google" or normalized.startswith(
350
+ ("vertex_ai/", "vertex_ai_beta/")
351
+ ):
352
+ return {"file_data_as_data_url"}
353
+ return set()
354
+
355
+
344
356
  class LiteLLMGenerator(Generator):
345
357
  """
346
358
  Generator backed by the LiteLLM library.
@@ -762,9 +774,13 @@ class LiteLLMGenerator(Generator):
762
774
  {k: v for k, v in merged.items() if k not in ("tools",)},
763
775
  )
764
776
 
777
+ compatibility_flags = _compatibility_flags_for_model(self.model)
765
778
  response = await acompletion(
766
779
  model=self.model,
767
- messages=[message.to_openai() for message in messages],
780
+ messages=[
781
+ message.to_openai(compatibility_flags=compatibility_flags)
782
+ for message in messages
783
+ ],
768
784
  api_key=self.api_key,
769
785
  **merged,
770
786
  )