dreadnode 2.0.6__tar.gz → 2.0.8__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 (430) hide show
  1. {dreadnode-2.0.6 → dreadnode-2.0.8}/PKG-INFO +1 -1
  2. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/agents/__init__.py +0 -1
  3. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/agents/agent.py +12 -13
  4. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/agents/events.py +18 -1
  5. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/agents/mcp/client.py +113 -58
  6. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/assessment.py +33 -19
  7. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/api/client.py +166 -48
  8. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/cli/airt.py +104 -81
  9. dreadnode-2.0.8/dreadnode/app/cli/args.py +224 -0
  10. dreadnode-2.0.8/dreadnode/app/cli/capability.py +594 -0
  11. dreadnode-2.0.8/dreadnode/app/cli/dataset.py +371 -0
  12. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/cli/evaluation.py +48 -45
  13. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/cli/main.py +193 -91
  14. dreadnode-2.0.8/dreadnode/app/cli/model.py +551 -0
  15. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/cli/optimize.py +88 -59
  16. dreadnode-2.0.8/dreadnode/app/cli/runtime.py +55 -0
  17. dreadnode-2.0.8/dreadnode/app/cli/shared.py +307 -0
  18. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/cli/task.py +82 -41
  19. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/cli/train.py +111 -65
  20. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/cli/worlds.py +144 -133
  21. dreadnode-2.0.8/dreadnode/app/config.py +503 -0
  22. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/main.py +124 -135
  23. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/print_mode.py +9 -24
  24. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/server/app.py +163 -73
  25. dreadnode-2.0.8/dreadnode/app/server/prompt.py +182 -0
  26. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/app.py +480 -247
  27. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/client.py +3 -4
  28. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/commands.py +118 -58
  29. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/dreadnode.tcss +44 -0
  30. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/model_variants.py +154 -7
  31. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/screens/auth.py +46 -17
  32. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/screens/base.py +5 -3
  33. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/screens/capabilities.py +394 -128
  34. dreadnode-2.0.8/dreadnode/app/tui/screens/connection_error.py +164 -0
  35. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/screens/console.py +7 -4
  36. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/screens/evaluations.py +10 -6
  37. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/screens/mcp.py +7 -19
  38. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/screens/runtimes.py +43 -47
  39. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/screens/sandboxes.py +16 -13
  40. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/turn_reducer.py +24 -0
  41. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/update_check.py +3 -1
  42. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/widgets/__init__.py +4 -0
  43. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/widgets/composer.py +10 -2
  44. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/widgets/context_bar.py +23 -6
  45. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/widgets/conversation.py +38 -22
  46. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/widgets/help_panel.py +4 -10
  47. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/widgets/overlay_mixin.py +13 -0
  48. dreadnode-2.0.8/dreadnode/app/tui/widgets/profile_dialog.py +128 -0
  49. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/widgets/prompt_info.py +10 -4
  50. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/widgets/status_bar.py +25 -12
  51. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/widgets/throbber.py +2 -2
  52. dreadnode-2.0.8/dreadnode/app/tui/widgets/tool.py +125 -0
  53. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/widgets/tool_progress.py +2 -1
  54. dreadnode-2.0.8/dreadnode/app/tui/widgets/whoami.py +76 -0
  55. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/capabilities/sync.py +255 -26
  56. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/core/load.py +13 -13
  57. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/core/log.py +3 -2
  58. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/generators/generator/base.py +9 -1
  59. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/generators/generator/litellm_.py +74 -3
  60. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/models/local.py +32 -0
  61. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/optimization/jobs.py +2 -2
  62. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/optimization/study.py +10 -4
  63. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/packaging/loader.py +2 -2
  64. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/packaging/manifest.py +11 -0
  65. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/packaging/oci.py +46 -5
  66. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/packaging/task_validation.py +1 -1
  67. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/storage/storage.py +15 -15
  68. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/tools/__init__.py +2 -6
  69. {dreadnode-2.0.6 → dreadnode-2.0.8}/pyproject.toml +54 -3
  70. dreadnode-2.0.6/dreadnode/app/cli/capability.py +0 -260
  71. dreadnode-2.0.6/dreadnode/app/cli/dataset.py +0 -139
  72. dreadnode-2.0.6/dreadnode/app/cli/model.py +0 -104
  73. dreadnode-2.0.6/dreadnode/app/cli/runtime.py +0 -52
  74. dreadnode-2.0.6/dreadnode/app/cli/shared.py +0 -771
  75. dreadnode-2.0.6/dreadnode/app/server/default-agent/tools/coding.py +0 -968
  76. dreadnode-2.0.6/dreadnode/app/server/default-agent/tools/subagent.py +0 -214
  77. dreadnode-2.0.6/dreadnode/app/server/session.py +0 -284
  78. dreadnode-2.0.6/dreadnode/app/server/system-prompt.md +0 -8
  79. dreadnode-2.0.6/dreadnode/app/tui/widgets/tool.py +0 -70
  80. {dreadnode-2.0.6 → dreadnode-2.0.8}/.gitignore +0 -0
  81. {dreadnode-2.0.6 → dreadnode-2.0.8}/LICENSE +0 -0
  82. {dreadnode-2.0.6 → dreadnode-2.0.8}/README.md +0 -0
  83. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/__init__.py +0 -0
  84. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/__main__.py +0 -0
  85. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/agents/exceptions.py +0 -0
  86. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/agents/format.py +0 -0
  87. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/agents/hooks.py +0 -0
  88. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/agents/mcp/__init__.py +0 -0
  89. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/agents/mcp/auth.py +0 -0
  90. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/agents/mcp/config.py +0 -0
  91. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/agents/mcp/server.py +0 -0
  92. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/agents/reactions.py +0 -0
  93. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/agents/skills.py +0 -0
  94. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/agents/stopping.py +0 -0
  95. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/agents/subagent.py +0 -0
  96. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/agents/tools.py +0 -0
  97. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/agents/trajectory.py +0 -0
  98. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/__init__.py +0 -0
  99. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/analytics/__init__.py +0 -0
  100. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/analytics/aggregator.py +0 -0
  101. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/analytics/classifier.py +0 -0
  102. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/analytics/compliance.py +0 -0
  103. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/analytics/engine.py +0 -0
  104. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/analytics/recommendations.py +0 -0
  105. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/analytics/types.py +0 -0
  106. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/autodan_turbo.py +0 -0
  107. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/beast.py +0 -0
  108. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/compliance/__init__.py +0 -0
  109. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/compliance/atlas.py +0 -0
  110. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/compliance/nist.py +0 -0
  111. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/compliance/owasp.py +0 -0
  112. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/compliance/owasp_agentic.py +0 -0
  113. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/compliance/saif.py +0 -0
  114. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/constants.py +0 -0
  115. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/crescendo.py +0 -0
  116. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/data/__init__.py +0 -0
  117. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/data/assets/audio/adversarial_query.mp3 +0 -0
  118. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/data/assets/image/bomb.jpg +0 -0
  119. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/data/assets/image/meth.png +0 -0
  120. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/data/prompts/adversarial_benchmark_subset.csv +0 -0
  121. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/data/prompts/ai_safety.csv +0 -0
  122. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/data/rubrics/data_exfiltration.yaml +0 -0
  123. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/data/rubrics/goal_hijacking.yaml +0 -0
  124. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/data/rubrics/memory_poisoning.yaml +0 -0
  125. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/data/rubrics/privilege_escalation.yaml +0 -0
  126. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/data/rubrics/rce.yaml +0 -0
  127. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/data/rubrics/scope_creep.yaml +0 -0
  128. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/data/rubrics/tool_chaining.yaml +0 -0
  129. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/data/rubrics/tool_selection_safety.yaml +0 -0
  130. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/data/rubrics/unbounded_agency.yaml +0 -0
  131. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/data/rubrics/web_chatbot_security.yaml +0 -0
  132. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/data/templates/crescendo/variant_1.yaml +0 -0
  133. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/data/templates/crescendo/variant_2.yaml +0 -0
  134. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/data/templates/crescendo/variant_3.yaml +0 -0
  135. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/data/templates/crescendo/variant_4.yaml +0 -0
  136. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/data/templates/crescendo/variant_5.yaml +0 -0
  137. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/deep_inception.py +0 -0
  138. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/drattack.py +0 -0
  139. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/events.py +0 -0
  140. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/goat.py +0 -0
  141. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/gptfuzzer.py +0 -0
  142. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/image.py +0 -0
  143. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/multimodal.py +0 -0
  144. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/pair.py +0 -0
  145. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/prompt.py +0 -0
  146. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/rainbow.py +0 -0
  147. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/renellm.py +0 -0
  148. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/reporting/__init__.py +0 -0
  149. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/reporting/json_report.py +0 -0
  150. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/reporting/llm_summary.py +0 -0
  151. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/reporting/markdown.py +0 -0
  152. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/airt/tap.py +0 -0
  153. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/__init__.py +0 -0
  154. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/api/__init__.py +0 -0
  155. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/api/models.py +0 -0
  156. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/cli/__init__.py +0 -0
  157. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/server/__init__.py +0 -0
  158. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/server/auth.py +0 -0
  159. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/server/utils.py +0 -0
  160. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/__init__.py +0 -0
  161. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/connection.py +0 -0
  162. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/event_contract.py +0 -0
  163. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/runtime_cache.py +0 -0
  164. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/screens/__init__.py +0 -0
  165. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/screens/environments.py +0 -0
  166. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/screens/model_picker.py +0 -0
  167. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/screens/secrets.py +0 -0
  168. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/screens/sessions.py +0 -0
  169. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/screens/theme_showcase.py +0 -0
  170. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/screens/traces.py +0 -0
  171. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/screens/workspaces.py +0 -0
  172. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/theme.py +0 -0
  173. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/widgets/agent_dialog.py +0 -0
  174. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/widgets/agent_suggester.py +0 -0
  175. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/widgets/flash.py +0 -0
  176. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/widgets/header_bar.py +0 -0
  177. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/widgets/mention_overlay.py +0 -0
  178. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/widgets/message_queue.py +0 -0
  179. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/widgets/permission_prompt.py +0 -0
  180. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/widgets/session_sidebar.py +0 -0
  181. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/widgets/skills_dialog.py +0 -0
  182. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/widgets/slash_overlay.py +0 -0
  183. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/widgets/tools_dialog.py +0 -0
  184. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/app/tui/widgets/welcome.py +0 -0
  185. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/capabilities/__init__.py +0 -0
  186. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/capabilities/capability.py +0 -0
  187. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/capabilities/loader.py +0 -0
  188. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/capabilities/tool_rules.py +0 -0
  189. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/capabilities/types.py +0 -0
  190. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/core/__init__.py +0 -0
  191. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/core/conditions.py +0 -0
  192. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/core/discovery.py +0 -0
  193. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/core/environment.py +0 -0
  194. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/core/exceptions.py +0 -0
  195. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/core/execution.py +0 -0
  196. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/core/hook.py +0 -0
  197. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/core/judge.py +0 -0
  198. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/core/meta/__init__.py +0 -0
  199. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/core/meta/config.py +0 -0
  200. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/core/meta/context.py +0 -0
  201. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/core/meta/hydrate.py +0 -0
  202. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/core/meta/introspect.py +0 -0
  203. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/core/metric.py +0 -0
  204. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/core/object.py +0 -0
  205. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/core/scorer.py +0 -0
  206. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/core/serialization.py +0 -0
  207. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/core/stopping.py +0 -0
  208. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/core/task.py +0 -0
  209. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/core/transforms.py +0 -0
  210. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/core/types/__init__.py +0 -0
  211. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/core/types/audio.py +0 -0
  212. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/core/types/base.py +0 -0
  213. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/core/types/common.py +0 -0
  214. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/core/types/image.py +0 -0
  215. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/core/types/object_3d.py +0 -0
  216. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/core/types/table.py +0 -0
  217. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/core/types/text.py +0 -0
  218. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/core/types/video.py +0 -0
  219. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/core/util.py +0 -0
  220. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/datasets/__init__.py +0 -0
  221. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/datasets/dataset.py +0 -0
  222. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/datasets/hf.py +0 -0
  223. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/datasets/local.py +0 -0
  224. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/evaluations/__init__.py +0 -0
  225. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/evaluations/console.py +0 -0
  226. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/evaluations/evaluation.py +0 -0
  227. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/evaluations/events.py +0 -0
  228. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/evaluations/format.py +0 -0
  229. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/evaluations/result.py +0 -0
  230. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/evaluations/sample.py +0 -0
  231. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/generators/__init__.py +0 -0
  232. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/generators/caching.py +0 -0
  233. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/generators/chat.py +0 -0
  234. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/generators/data.py +0 -0
  235. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/generators/exceptions.py +0 -0
  236. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/generators/generator/__init__.py +0 -0
  237. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/generators/generator/http.py +0 -0
  238. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/generators/generator/transformers_.py +0 -0
  239. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/generators/generator/vllm_.py +0 -0
  240. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/generators/message.py +0 -0
  241. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/generators/models.py +0 -0
  242. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/generators/parsing.py +0 -0
  243. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/generators/tokenizer/__init__.py +0 -0
  244. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/generators/tokenizer/base.py +0 -0
  245. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/generators/tokenizer/transformers_.py +0 -0
  246. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/generators/utils.py +0 -0
  247. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/models/__init__.py +0 -0
  248. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/models/hf.py +0 -0
  249. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/models/model.py +0 -0
  250. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/optimization/__init__.py +0 -0
  251. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/optimization/adapters/__init__.py +0 -0
  252. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/optimization/adapters/agent.py +0 -0
  253. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/optimization/api.py +0 -0
  254. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/optimization/backends/__init__.py +0 -0
  255. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/optimization/backends/base.py +0 -0
  256. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/optimization/backends/gepa.py +0 -0
  257. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/optimization/collectors.py +0 -0
  258. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/optimization/config.py +0 -0
  259. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/optimization/console.py +0 -0
  260. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/optimization/events.py +0 -0
  261. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/optimization/format.py +0 -0
  262. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/optimization/result.py +0 -0
  263. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/optimization/sampler.py +0 -0
  264. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/optimization/sampling.py +0 -0
  265. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/optimization/search.py +0 -0
  266. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/optimization/stopping.py +0 -0
  267. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/optimization/trial.py +0 -0
  268. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/packaging/__init__.py +0 -0
  269. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/packaging/package.py +0 -0
  270. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/py.typed +0 -0
  271. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/samplers/__init__.py +0 -0
  272. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/samplers/boundary.py +0 -0
  273. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/samplers/fuzzing.py +0 -0
  274. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/samplers/graph.py +0 -0
  275. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/samplers/grid.py +0 -0
  276. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/samplers/image.py +0 -0
  277. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/samplers/mapelites.py +0 -0
  278. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/samplers/optuna.py +0 -0
  279. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/samplers/random.py +0 -0
  280. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/samplers/registry.py +0 -0
  281. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/samplers/strategy.py +0 -0
  282. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/scorers/__init__.py +0 -0
  283. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/scorers/advanced_jailbreak_detection.py +0 -0
  284. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/scorers/agent_security.py +0 -0
  285. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/scorers/agentic.py +0 -0
  286. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/scorers/agentic_workflow.py +0 -0
  287. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/scorers/classification.py +0 -0
  288. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/scorers/consistency.py +0 -0
  289. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/scorers/contains.py +0 -0
  290. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/scorers/cosine_sim.py +0 -0
  291. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/scorers/credentials.py +0 -0
  292. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/scorers/crucible.py +0 -0
  293. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/scorers/documentation_security.py +0 -0
  294. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/scorers/exfiltration_detection.py +0 -0
  295. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/scorers/format.py +0 -0
  296. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/scorers/harm.py +0 -0
  297. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/scorers/ide_security.py +0 -0
  298. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/scorers/image.py +0 -0
  299. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/scorers/json.py +0 -0
  300. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/scorers/judge.py +0 -0
  301. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/scorers/length.py +0 -0
  302. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/scorers/lexical.py +0 -0
  303. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/scorers/mcp_security.py +0 -0
  304. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/scorers/memorization.py +0 -0
  305. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/scorers/multi_agent_security.py +0 -0
  306. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/scorers/pii.py +0 -0
  307. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/scorers/prompt_leak.py +0 -0
  308. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/scorers/readability.py +0 -0
  309. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/scorers/reasoning_security.py +0 -0
  310. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/scorers/sentiment.py +0 -0
  311. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/scorers/similarity.py +0 -0
  312. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/storage/__init__.py +0 -0
  313. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/storage/providers.py +0 -0
  314. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/storage/session_store.py +0 -0
  315. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/tools/_ripgrep.py +0 -0
  316. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/tools/apply_patch.py +0 -0
  317. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/tools/editing.py +0 -0
  318. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/tools/execute.py +0 -0
  319. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/tools/fetch.py +0 -0
  320. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/tools/glob.py +0 -0
  321. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/tools/grep.py +0 -0
  322. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/tools/interaction.py +0 -0
  323. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/tools/ls.py +0 -0
  324. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/tools/memory.py +0 -0
  325. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/tools/read.py +0 -0
  326. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/tools/task.py +0 -0
  327. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/tools/think.py +0 -0
  328. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/tools/todo.py +0 -0
  329. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/tools/web_search.py +0 -0
  330. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/tools/write.py +0 -0
  331. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/tracing/__init__.py +0 -0
  332. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/tracing/constants.py +0 -0
  333. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/tracing/convert.py +0 -0
  334. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/tracing/exporter.py +0 -0
  335. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/tracing/exporters.py +0 -0
  336. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/tracing/span.py +0 -0
  337. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/tracing/spans.py +0 -0
  338. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/tracing/trace_converter.py +0 -0
  339. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/__init__.py +0 -0
  340. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/base.py +0 -0
  341. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/dpo.py +0 -0
  342. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/etl/__init__.py +0 -0
  343. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/etl/_common.py +0 -0
  344. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/etl/rl.py +0 -0
  345. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/etl/sft.py +0 -0
  346. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/etl/worlds.py +0 -0
  347. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/events.py +0 -0
  348. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/grpo.py +0 -0
  349. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/jobs.py +0 -0
  350. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/ppo.py +0 -0
  351. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/prime.py +0 -0
  352. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/ray/__init__.py +0 -0
  353. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/ray/async_trainer.py +0 -0
  354. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/ray/config.py +0 -0
  355. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/ray/coordinator.py +0 -0
  356. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/ray/distributed.py +0 -0
  357. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/ray/dpo.py +0 -0
  358. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/ray/experience.py +0 -0
  359. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/ray/fsdp2_learner.py +0 -0
  360. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/ray/inference.py +0 -0
  361. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/ray/learner.py +0 -0
  362. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/ray/multi_turn.py +0 -0
  363. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/ray/ppo.py +0 -0
  364. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/ray/reward_model.py +0 -0
  365. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/ray/rollout_env.py +0 -0
  366. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/ray/rollout_worker.py +0 -0
  367. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/ray/sft.py +0 -0
  368. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/ray/trainer.py +0 -0
  369. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/recipes.py +0 -0
  370. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/rewards/__init__.py +0 -0
  371. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/rewards/aggregator.py +0 -0
  372. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/rewards/functions.py +0 -0
  373. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/rewards/scorer_bridge.py +0 -0
  374. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/rewards/shaping.py +0 -0
  375. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/rewards/types.py +0 -0
  376. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/rollouts/__init__.py +0 -0
  377. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/rollouts/adapters.py +0 -0
  378. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/rollouts/orchestrator.py +0 -0
  379. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/rollouts/types.py +0 -0
  380. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/rollouts/worlds.py +0 -0
  381. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/serving/__init__.py +0 -0
  382. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/serving/vllm_client.py +0 -0
  383. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/sft.py +0 -0
  384. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/tinker/__init__.py +0 -0
  385. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/tinker/config.py +0 -0
  386. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/tinker/data.py +0 -0
  387. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/tinker/renderer.py +0 -0
  388. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/tinker/rl.py +0 -0
  389. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/tinker/trainer.py +0 -0
  390. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/tinker_sft.py +0 -0
  391. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/training/utils.py +0 -0
  392. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/transforms/__init__.py +0 -0
  393. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/transforms/advanced_jailbreak.py +0 -0
  394. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/transforms/adversarial_suffix.py +0 -0
  395. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/transforms/agent_skill.py +0 -0
  396. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/transforms/agentic_workflow.py +0 -0
  397. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/transforms/audio.py +0 -0
  398. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/transforms/browser_agent_attacks.py +0 -0
  399. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/transforms/cipher.py +0 -0
  400. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/transforms/constitutional.py +0 -0
  401. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/transforms/document.py +0 -0
  402. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/transforms/documentation_poison.py +0 -0
  403. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/transforms/encoding.py +0 -0
  404. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/transforms/exfiltration.py +0 -0
  405. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/transforms/flip_attack.py +0 -0
  406. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/transforms/guardrail_bypass.py +0 -0
  407. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/transforms/ide_injection.py +0 -0
  408. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/transforms/image.py +0 -0
  409. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/transforms/injection.py +0 -0
  410. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/transforms/json_tools.py +0 -0
  411. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/transforms/language.py +0 -0
  412. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/transforms/logic_bomb.py +0 -0
  413. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/transforms/mcp_attacks.py +0 -0
  414. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/transforms/multi_agent_attacks.py +0 -0
  415. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/transforms/persuasion.py +0 -0
  416. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/transforms/perturbation.py +0 -0
  417. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/transforms/pii_extraction.py +0 -0
  418. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/transforms/pythonic_tools.py +0 -0
  419. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/transforms/rag_poisoning.py +0 -0
  420. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/transforms/reasoning_attacks.py +0 -0
  421. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/transforms/refine.py +0 -0
  422. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/transforms/response_steering.py +0 -0
  423. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/transforms/stylistic.py +0 -0
  424. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/transforms/substitution.py +0 -0
  425. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/transforms/swap.py +0 -0
  426. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/transforms/system_prompt_extraction.py +0 -0
  427. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/transforms/text.py +0 -0
  428. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/transforms/video.py +0 -0
  429. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/transforms/xml_tools.py +0 -0
  430. {dreadnode-2.0.6 → dreadnode-2.0.8}/dreadnode/version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dreadnode
3
- Version: 2.0.6
3
+ Version: 2.0.8
4
4
  Summary: Dreadnode SDK
5
5
  Project-URL: Homepage, https://dreadnode.io
6
6
  Project-URL: Documentation, https://docs.dreadnode.io
@@ -2,7 +2,6 @@ import importlib
2
2
  import typing as t
3
3
 
4
4
  from dreadnode.agents import exceptions
5
- from dreadnode.agents.agent import Agent
6
5
  from dreadnode.agents.tools import (
7
6
  FunctionCall,
8
7
  FunctionDefinition,
@@ -669,6 +669,18 @@ class Agent(Executor[AgentEvent, Trajectory]):
669
669
  msg.metadata.setdefault("model", self.model_name)
670
670
  messages.extend(step_chat.generated)
671
671
 
672
+ # Emit content for TUI rendering BEFORE tools/stop-checks
673
+ # so text is visible immediately (ENG-5879)
674
+ last_msg = step_chat.generated[-1] if step_chat.generated else None
675
+ if last_msg and last_msg.content:
676
+ yield GenerationContent(
677
+ agent_id=self.agent_id,
678
+ agent_name=self.name,
679
+ step=step_count,
680
+ content=str(last_msg.content),
681
+ extra=step_chat.extra,
682
+ )
683
+
672
684
  # Check stop conditions INSIDE span
673
685
  if any(cond(self.trajectory.steps) for cond in self.stop_conditions):
674
686
  logger.info("A stop condition was met. Ending run.")
@@ -794,19 +806,6 @@ class Agent(Executor[AgentEvent, Trajectory]):
794
806
  finally:
795
807
  await _event_queue.put(None) # Signal done
796
808
 
797
- # Emit generation content BEFORE tools so TUI can
798
- # render text immediately (ENG-5879)
799
- last_msg = step_chat.generated[-1] if step_chat.generated else None
800
- if last_msg and last_msg.content:
801
- content_event = GenerationContent(
802
- agent_id=self.agent_id,
803
- agent_name=self.name,
804
- step=step_count,
805
- content=str(last_msg.content)[:4000],
806
- extra=step_chat.extra,
807
- )
808
- yield content_event
809
-
810
809
  # Start tools in background
811
810
  tools_task = asyncio.create_task(run_all_tools())
812
811
 
@@ -890,9 +890,26 @@ class GenerationError(AgentEvent):
890
890
  messages: list["Message"] = Field(default_factory=list)
891
891
 
892
892
  def _get_data(self) -> dict[str, t.Any]:
893
+ error_str = str(self.error)
894
+ # When litellm wraps provider exceptions with empty messages (e.g.
895
+ # "AnthropicException - ."), enrich with the underlying cause so the
896
+ # user gets something actionable instead of a cryptic dot.
897
+ if error_str.endswith(
898
+ ("Exception - .", "Exception - . Handle with `litellm.InternalServerError`.")
899
+ ):
900
+ cause = getattr(self.error, "__cause__", None) or getattr(
901
+ self.error, "__context__", None
902
+ )
903
+ if cause:
904
+ error_str = f"{error_str} (cause: {cause})"
905
+ else:
906
+ error_str = (
907
+ f"{type(self.error).__name__}: The API returned an error with no details. "
908
+ "This is usually a transient issue — try again."
909
+ )
893
910
  return {
894
911
  "model": self.generator.model if self.generator else None,
895
- "error": str(self.error),
912
+ "error": error_str,
896
913
  "error_type": type(self.error).__name__,
897
914
  "step": self.step,
898
915
  }
@@ -144,6 +144,10 @@ class MCPClient:
144
144
  _exit_stack: AsyncExitStack
145
145
  _session: "ClientSession | None"
146
146
  _oauth_config: t.Any # OAuthConfig | None
147
+ _owner_task: asyncio.Task[None] | None
148
+ _shutdown_event: asyncio.Event | None
149
+ _ready_future: asyncio.Future[None] | None
150
+ _lifecycle_lock: asyncio.Lock | None
147
151
 
148
152
  def __init__(
149
153
  self,
@@ -173,6 +177,10 @@ class MCPClient:
173
177
  self._oauth_config = oauth
174
178
  self._init_timeout = init_timeout
175
179
  self._stderr_capture: _StderrCapture | None = None
180
+ self._owner_task = None
181
+ self._shutdown_event = None
182
+ self._ready_future = None
183
+ self._lifecycle_lock = None
176
184
 
177
185
  @classmethod
178
186
  def from_config(cls, config: ServerConfig) -> "MCPClient":
@@ -222,6 +230,83 @@ class MCPClient:
222
230
 
223
231
  return execute_on_server
224
232
 
233
+ def _get_lifecycle_lock(self) -> asyncio.Lock:
234
+ if self._lifecycle_lock is None:
235
+ self._lifecycle_lock = asyncio.Lock()
236
+ return self._lifecycle_lock
237
+
238
+ @staticmethod
239
+ def _unwrap_exception(exc: BaseException) -> BaseException:
240
+ cause = exc
241
+ if isinstance(exc, BaseExceptionGroup):
242
+ leaf = exc.exceptions[0] if exc.exceptions else exc
243
+ while isinstance(leaf, BaseExceptionGroup) and leaf.exceptions:
244
+ leaf = leaf.exceptions[0]
245
+ cause = leaf
246
+ return cause
247
+
248
+ def _set_error_status(self, exc: BaseException) -> BaseException:
249
+ cause = self._unwrap_exception(exc)
250
+ error_msg = str(cause)
251
+
252
+ if self._stderr_capture and self._stderr_capture.last_lines:
253
+ stderr_tail = "\n".join(self._stderr_capture.last_lines[-10:])
254
+ error_msg = f"{error_msg}\n\nServer stderr:\n{stderr_tail}"
255
+
256
+ error_lower = error_msg.lower()
257
+ if "unauthorized" in error_lower or "401" in error_lower or "oauth" in error_lower:
258
+ self._status = MCPStatus.NEEDS_AUTH
259
+ else:
260
+ self._status = MCPStatus.FAILED
261
+
262
+ self._error = error_msg
263
+ return cause
264
+
265
+ def _reset_connection_state(self) -> None:
266
+ self._session = None
267
+ self.tools.clear()
268
+ if self._status == MCPStatus.CONNECTED:
269
+ self._status = MCPStatus.DISCONNECTED
270
+ self._exit_stack = AsyncExitStack()
271
+ self._stderr_capture = None
272
+
273
+ async def _run_connection(self, shutdown_event: asyncio.Event) -> None:
274
+ try:
275
+ if self.transport == "stdio":
276
+ self._session = await self._connect_via_stdio(
277
+ t.cast("StdioConnection", self.connection),
278
+ )
279
+ elif self.transport == "streamable-http":
280
+ self._session = await self._connect_via_streamable_http(
281
+ t.cast("dict[str, t.Any]", self.connection),
282
+ )
283
+ else:
284
+ msg = (
285
+ f"Unsupported transport: {self.transport}. Must be 'stdio' or 'streamable-http'"
286
+ )
287
+ raise TypeError(msg) # noqa: TRY301
288
+
289
+ await asyncio.wait_for(self.session.initialize(), timeout=self._init_timeout)
290
+ await asyncio.wait_for(self._load_tools(), timeout=self._init_timeout)
291
+
292
+ self._status = MCPStatus.CONNECTED
293
+ self._error = None
294
+
295
+ if self._ready_future is not None and not self._ready_future.done():
296
+ self._ready_future.set_result(None)
297
+
298
+ await shutdown_event.wait()
299
+ except BaseException as exc:
300
+ cause = self._set_error_status(exc)
301
+ if self._ready_future is not None and not self._ready_future.done():
302
+ if isinstance(cause, Exception):
303
+ self._ready_future.set_exception(cause)
304
+ else:
305
+ self._ready_future.set_exception(RuntimeError(str(cause)))
306
+ finally:
307
+ await self._exit_stack.aclose()
308
+ self._reset_connection_state()
309
+
225
310
  async def _load_tools(self) -> None:
226
311
  mcp_tool_result = await self.session.list_tools()
227
312
 
@@ -378,73 +463,43 @@ class MCPClient:
378
463
 
379
464
  Sets status to CONNECTED on success, FAILED or NEEDS_AUTH on error.
380
465
  """
381
- try:
382
- if self.transport == "stdio":
383
- self._session = await self._connect_via_stdio(
384
- t.cast("StdioConnection", self.connection),
385
- )
386
- elif self.transport == "streamable-http":
387
- self._session = await self._connect_via_streamable_http(
388
- t.cast("dict[str, t.Any]", self.connection),
389
- )
466
+ async with self._get_lifecycle_lock():
467
+ if self._owner_task is not None and not self._owner_task.done():
468
+ ready_future = self._ready_future
390
469
  else:
391
- raise TypeError( # noqa: TRY301 - intentional routing through shared connection failure handling
392
- f"Unsupported transport: {self.transport}. "
393
- "Must be 'stdio' or 'streamable-http'",
470
+ self._reset_connection_state()
471
+ self._shutdown_event = asyncio.Event()
472
+ self._ready_future = asyncio.get_running_loop().create_future()
473
+ self._owner_task = asyncio.create_task(
474
+ self._run_connection(self._shutdown_event),
475
+ name=f"mcp-client:{self.transport}",
394
476
  )
477
+ ready_future = self._ready_future
395
478
 
396
- await asyncio.wait_for(self.session.initialize(), timeout=self._init_timeout)
397
- await asyncio.wait_for(self._load_tools(), timeout=self._init_timeout)
398
-
399
- self._status = MCPStatus.CONNECTED
400
- self._error = None
401
-
402
- except BaseException as e:
403
- await self._shutdown()
404
-
405
- # anyio TaskGroups wrap failures in BaseExceptionGroup — unwrap
406
- # to surface the actual root cause (e.g. ConnectionRefusedError)
407
- # instead of the opaque "unhandled errors in a TaskGroup" message.
408
- cause = e
409
- if isinstance(e, BaseExceptionGroup):
410
- leaf = e.exceptions[0] if e.exceptions else e
411
- while isinstance(leaf, BaseExceptionGroup) and leaf.exceptions:
412
- leaf = leaf.exceptions[0]
413
- cause = leaf
414
-
415
- error_msg = str(cause)
416
-
417
- # Append captured subprocess stderr for stdio failures —
418
- # this surfaces the actual crash output (tracebacks, missing
419
- # modules, config errors) instead of just "Connection closed".
420
- if self._stderr_capture and self._stderr_capture.last_lines:
421
- stderr_tail = "\n".join(self._stderr_capture.last_lines[-10:])
422
- error_msg = f"{error_msg}\n\nServer stderr:\n{stderr_tail}"
423
-
424
- # Check for auth-related failures
425
- error_lower = error_msg.lower()
426
- if "unauthorized" in error_lower or "401" in error_lower or "oauth" in error_lower:
427
- self._status = MCPStatus.NEEDS_AUTH
428
- else:
429
- self._status = MCPStatus.FAILED
430
-
431
- self._error = error_msg
432
-
433
- # Re-raise the unwrapped cause so callers can catch with `except Exception`
434
- if cause is not e and isinstance(cause, Exception):
435
- raise cause from e
436
- raise
479
+ assert ready_future is not None
480
+ await ready_future
437
481
 
438
482
  async def disconnect(self) -> None:
439
483
  """Disconnect from the MCP server."""
440
484
  await self._shutdown()
441
485
 
442
486
  async def _shutdown(self) -> None:
443
- await self._exit_stack.aclose()
444
- self._session = None
445
- self.tools.clear()
446
- if self._status == MCPStatus.CONNECTED:
447
- self._status = MCPStatus.DISCONNECTED
487
+ async with self._get_lifecycle_lock():
488
+ owner_task = self._owner_task
489
+ shutdown_event = self._shutdown_event
490
+ if owner_task is None:
491
+ self._reset_connection_state()
492
+ return
493
+ if shutdown_event is not None:
494
+ shutdown_event.set()
495
+
496
+ await owner_task
497
+
498
+ async with self._get_lifecycle_lock():
499
+ if self._owner_task is owner_task:
500
+ self._owner_task = None
501
+ self._shutdown_event = None
502
+ self._ready_future = None
448
503
 
449
504
  async def __aenter__(self) -> "MCPClient":
450
505
  await self.connect()
@@ -36,7 +36,7 @@ if t.TYPE_CHECKING:
36
36
 
37
37
  from dreadnode.airt.analytics.types import GoalCategory
38
38
  from dreadnode.app.api.client import ApiClient
39
- from dreadnode.app.server.session import Session
39
+ from dreadnode.app.config import Profile
40
40
  from dreadnode.core.task import Task
41
41
  from dreadnode.optimization.study import Study
42
42
 
@@ -45,13 +45,13 @@ _current_assessment: contextvars.ContextVar[Assessment | None] = contextvars.Con
45
45
  )
46
46
 
47
47
 
48
- def _get_platform_context() -> tuple[ApiClient, Session] | None:
49
- """Get the API client and session if connected to the platform."""
48
+ def _get_platform_context() -> tuple[ApiClient, Profile] | None:
49
+ """Get the API client and profile if connected to the platform."""
50
50
  try:
51
51
  from dreadnode.app.main import DEFAULT_INSTANCE
52
52
 
53
53
  if DEFAULT_INSTANCE.can_sync:
54
- return DEFAULT_INSTANCE.api, DEFAULT_INSTANCE.session
54
+ return DEFAULT_INSTANCE.api, DEFAULT_INSTANCE.profile
55
55
  except Exception:
56
56
  logger.debug("Unable to resolve platform context for AIRT assessment")
57
57
  return None
@@ -82,6 +82,9 @@ class Assessment:
82
82
  attack_defaults: dict[str, t.Any] | None = None,
83
83
  description: str | None = None,
84
84
  session_id: str | None = None,
85
+ target_model: str | None = None,
86
+ attacker_model: str | None = None,
87
+ judge_model: str | None = None,
85
88
  target_config: dict[str, t.Any] | None = None,
86
89
  attacker_config: dict[str, t.Any] | None = None,
87
90
  attack_manifest: list[dict[str, t.Any]] | None = None,
@@ -97,6 +100,11 @@ class Assessment:
97
100
  self.goal_category = goal_category
98
101
  self._attack_defaults = attack_defaults or {}
99
102
 
103
+ # First-class model identifiers for platform UI
104
+ self.target_model = target_model or model
105
+ self.attacker_model = attacker_model or model
106
+ self.judge_model = judge_model or model
107
+
100
108
  if target_config is None and model is not None:
101
109
  target_config = {"model": model}
102
110
  if attacker_config is None and model is not None:
@@ -143,15 +151,18 @@ class Assessment:
143
151
  Returns:
144
152
  The platform assessment ID, or None if offline.
145
153
  """
154
+ if self._assessment_id is not None:
155
+ return self._assessment_id
156
+
146
157
  ctx = _get_platform_context()
147
158
  if ctx is None:
148
159
  logger.debug("SDK offline -- assessment not registered with platform")
149
160
  return None
150
161
 
151
- api, session = ctx
162
+ api, profile = ctx
152
163
  project_id = self._project_id
153
- if project_id is None and session.project is not None:
154
- project_id = session.project.id
164
+ if project_id is None and profile.project_id is not None:
165
+ project_id = profile.project_id
155
166
 
156
167
  if project_id is None:
157
168
  logger.warning("No project_id available -- cannot register assessment")
@@ -159,12 +170,15 @@ class Assessment:
159
170
 
160
171
  try:
161
172
  result = api.create_airt_assessment(
162
- session.org_key,
163
- session.workspace_key,
173
+ profile.org_key,
174
+ profile.workspace_key,
164
175
  name=self.name,
165
176
  project_id=project_id,
166
177
  description=self.description,
167
178
  session_id=self._session_id,
179
+ target_model=self.target_model,
180
+ attacker_model=self.attacker_model,
181
+ judge_model=self.judge_model,
168
182
  target_config=self.target_config,
169
183
  attacker_config=self.attacker_config,
170
184
  attack_manifest=self._attack_manifest,
@@ -319,7 +333,7 @@ class Assessment:
319
333
 
320
334
  merged = {**self._attack_defaults, **kwargs}
321
335
  merged.setdefault("airt_goal_category", self.goal_category)
322
- merged.setdefault("airt_target_model", model)
336
+ merged.setdefault("airt_target_model", self.target_model or model)
323
337
 
324
338
  return factory(goal, target, model, model, **merged)
325
339
 
@@ -383,9 +397,9 @@ class Assessment:
383
397
  if ctx is None or self._assessment_id is None:
384
398
  return None
385
399
 
386
- api, session = ctx
387
- org = session.org_key
388
- ws = session.workspace_key
400
+ api, profile = ctx
401
+ org = profile.org_key
402
+ ws = profile.workspace_key
389
403
 
390
404
  try:
391
405
  trace_id = uuid.uuid4().hex
@@ -439,11 +453,11 @@ class Assessment:
439
453
  if ctx is None or self._assessment_id is None:
440
454
  return False
441
455
 
442
- api, session = ctx
456
+ api, profile = ctx
443
457
  try:
444
458
  api.update_airt_assessment(
445
- session.org_key,
446
- session.workspace_key,
459
+ profile.org_key,
460
+ profile.workspace_key,
447
461
  self._assessment_id,
448
462
  status="completed",
449
463
  )
@@ -467,14 +481,14 @@ class Assessment:
467
481
  if ctx is None or self._assessment_id is None:
468
482
  return False
469
483
 
470
- api, session = ctx
484
+ api, profile = ctx
471
485
  try:
472
486
  kwargs: dict[str, t.Any] = {"status": "failed"}
473
487
  if reason:
474
488
  kwargs["description"] = f"{self.description or ''}\n\nFailure: {reason}".strip()
475
489
  api.update_airt_assessment(
476
- session.org_key,
477
- session.workspace_key,
490
+ profile.org_key,
491
+ profile.workspace_key,
478
492
  self._assessment_id,
479
493
  **kwargs,
480
494
  )