dreadnode 2.0.27__tar.gz → 2.0.29__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 (638) hide show
  1. {dreadnode-2.0.27 → dreadnode-2.0.29}/PKG-INFO +1 -1
  2. dreadnode-2.0.29/dreadnode/agents/mcp/auth.py +486 -0
  3. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/agents/mcp/client.py +135 -12
  4. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/agents/process_judge.py +97 -9
  5. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/autodan_turbo.py +12 -0
  6. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/beast.py +12 -0
  7. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/deep_inception.py +12 -0
  8. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/drattack.py +12 -0
  9. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/gptfuzzer.py +12 -0
  10. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/image.py +24 -0
  11. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/multimodal.py +12 -0
  12. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/rainbow.py +12 -0
  13. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/renellm.py +12 -0
  14. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/api/client.py +9 -1
  15. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/api/models.py +39 -1
  16. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/cli/evaluation.py +4 -0
  17. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/cli/task.py +98 -16
  18. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/cli/train.py +14 -2
  19. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/client/runtime_client.py +21 -0
  20. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/main.py +26 -1
  21. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/model_catalog.py +1 -1
  22. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/print_mode.py +7 -0
  23. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/server/app.py +79 -3
  24. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/server/capability_manager.py +415 -117
  25. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/app.py +113 -49
  26. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/capabilities_manager.py +17 -4
  27. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/dreadnode.tcss +20 -5
  28. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/model_manager.py +10 -60
  29. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/screen_router.py +8 -2
  30. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/screens/__init__.py +0 -2
  31. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/screens/capabilities.py +45 -0
  32. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/screens/runtimes.py +53 -0
  33. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/screens/sandboxes.py +18 -0
  34. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/screens/services.py +576 -199
  35. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/tool_format.py +20 -3
  36. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/widgets/composer.py +0 -2
  37. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/widgets/help_panel.py +1 -1
  38. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/widgets/rewind_picker.py +1 -2
  39. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/INDEX.md +0 -1
  40. dreadnode-2.0.29/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/mcp-servers.md +277 -0
  41. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/writing-skills.md +0 -2
  42. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/sdk/agents.md +3 -1
  43. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/sdk/capabilities.md +30 -0
  44. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/evaluation.md +1 -0
  45. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/task.md +3 -1
  46. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/train.md +2 -2
  47. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/INDEX.md +1 -0
  48. dreadnode-2.0.29/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/getting-started/quickstart.md +165 -0
  49. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/chat-models.md +34 -38
  50. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/credits.md +8 -0
  51. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/organizations.md +2 -1
  52. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/secrets.md +4 -2
  53. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/settings.md +4 -4
  54. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/sandboxes/environment-lifecycle.md +0 -1
  55. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/sandboxes/inspecting.md +2 -0
  56. dreadnode-2.0.29/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/sandboxes/runtime-limits.md +55 -0
  57. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/capabilities/loader.py +61 -1
  58. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/capabilities/types.py +77 -2
  59. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/generators/generator/litellm_.py +9 -0
  60. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/packaging/oci.py +23 -3
  61. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/packaging/task_validation.py +38 -9
  62. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/policies/guard.py +20 -0
  63. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/scorers/judge.py +31 -20
  64. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/tools/read.py +28 -5
  65. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/jobs.py +20 -4
  66. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/tinker/config.py +16 -3
  67. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/tinker/trainer.py +131 -30
  68. {dreadnode-2.0.27 → dreadnode-2.0.29}/pyproject.toml +3 -1
  69. dreadnode-2.0.27/dreadnode/agents/mcp/auth.py +0 -149
  70. dreadnode-2.0.27/dreadnode/app/tui/screens/model_picker.py +0 -127
  71. dreadnode-2.0.27/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/mcp-servers.md +0 -174
  72. dreadnode-2.0.27/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/guides/capability-optimization-loop.md +0 -133
  73. dreadnode-2.0.27/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/getting-started/quickstart.md +0 -134
  74. {dreadnode-2.0.27 → dreadnode-2.0.29}/.gitignore +0 -0
  75. {dreadnode-2.0.27 → dreadnode-2.0.29}/LICENSE +0 -0
  76. {dreadnode-2.0.27 → dreadnode-2.0.29}/README.md +0 -0
  77. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/__init__.py +0 -0
  78. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/__main__.py +0 -0
  79. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/agents/__init__.py +0 -0
  80. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/agents/agent.py +0 -0
  81. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/agents/events.py +0 -0
  82. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/agents/exceptions.py +0 -0
  83. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/agents/format.py +0 -0
  84. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/agents/hooks.py +0 -0
  85. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/agents/judge.py +0 -0
  86. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/agents/mcp/__init__.py +0 -0
  87. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/agents/mcp/config.py +0 -0
  88. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/agents/mcp/server.py +0 -0
  89. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/agents/reactions.py +0 -0
  90. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/agents/skills.py +0 -0
  91. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/agents/stopping.py +0 -0
  92. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/agents/subagent.py +0 -0
  93. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/agents/tool_resolution.py +0 -0
  94. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/agents/tools.py +0 -0
  95. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/agents/trajectory.py +0 -0
  96. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/__init__.py +0 -0
  97. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/adversarial_reasoning.py +0 -0
  98. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/advpromptier.py +0 -0
  99. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/alignment_faking.py +0 -0
  100. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/analogy_escalation.py +0 -0
  101. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/analytics/__init__.py +0 -0
  102. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/analytics/aggregator.py +0 -0
  103. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/analytics/classifier.py +0 -0
  104. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/analytics/compliance.py +0 -0
  105. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/analytics/engine.py +0 -0
  106. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/analytics/recommendations.py +0 -0
  107. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/analytics/types.py +0 -0
  108. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/aprt_progressive.py +0 -0
  109. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/assessment.py +0 -0
  110. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/attention_shifting.py +0 -0
  111. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/autoredteamer.py +0 -0
  112. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/compliance/__init__.py +0 -0
  113. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/compliance/atlas.py +0 -0
  114. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/compliance/nist.py +0 -0
  115. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/compliance/owasp.py +0 -0
  116. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/compliance/owasp_agentic.py +0 -0
  117. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/compliance/saif.py +0 -0
  118. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/constants.py +0 -0
  119. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/cot_jailbreak.py +0 -0
  120. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/crescendo.py +0 -0
  121. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/data/__init__.py +0 -0
  122. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/data/assets/audio/adversarial_query.mp3 +0 -0
  123. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/data/assets/image/bomb.jpg +0 -0
  124. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/data/assets/image/meth.png +0 -0
  125. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/data/prompts/adversarial_benchmark_subset.csv +0 -0
  126. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/data/prompts/ai_safety.csv +0 -0
  127. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/data/rubrics/data_exfiltration.yaml +0 -0
  128. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/data/rubrics/goal_hijacking.yaml +0 -0
  129. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/data/rubrics/idor.yaml +0 -0
  130. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/data/rubrics/memory_poisoning.yaml +0 -0
  131. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/data/rubrics/privilege_escalation.yaml +0 -0
  132. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/data/rubrics/rce.yaml +0 -0
  133. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/data/rubrics/scope_creep.yaml +0 -0
  134. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/data/rubrics/tool_chaining.yaml +0 -0
  135. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/data/rubrics/tool_selection_safety.yaml +0 -0
  136. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/data/rubrics/unbounded_agency.yaml +0 -0
  137. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/data/rubrics/web_chatbot_security.yaml +0 -0
  138. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/data/templates/crescendo/variant_1.yaml +0 -0
  139. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/data/templates/crescendo/variant_2.yaml +0 -0
  140. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/data/templates/crescendo/variant_3.yaml +0 -0
  141. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/data/templates/crescendo/variant_4.yaml +0 -0
  142. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/data/templates/crescendo/variant_5.yaml +0 -0
  143. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/echo_chamber.py +0 -0
  144. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/events.py +0 -0
  145. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/genetic_persona.py +0 -0
  146. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/goat.py +0 -0
  147. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/goat_v2.py +0 -0
  148. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/humor_bypass.py +0 -0
  149. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/j2_meta.py +0 -0
  150. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/jbdistill.py +0 -0
  151. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/jbfuzz.py +0 -0
  152. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/lrm_autonomous.py +0 -0
  153. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/mapf.py +0 -0
  154. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/nexus.py +0 -0
  155. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/pair.py +0 -0
  156. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/persona_hijack.py +0 -0
  157. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/prompt.py +0 -0
  158. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/quantization_safety.py +0 -0
  159. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/refusal_aware.py +0 -0
  160. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/reporting/__init__.py +0 -0
  161. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/reporting/json_report.py +0 -0
  162. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/reporting/llm_summary.py +0 -0
  163. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/reporting/markdown.py +0 -0
  164. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/reward_hacking.py +0 -0
  165. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/salami_slicing.py +0 -0
  166. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/self_persuasion.py +0 -0
  167. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/siren.py +0 -0
  168. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/tap.py +0 -0
  169. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/templatefuzz.py +0 -0
  170. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/tmap_trajectory.py +0 -0
  171. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/trojail.py +0 -0
  172. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/airt/watermark_removal.py +0 -0
  173. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/__init__.py +0 -0
  174. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/api/__init__.py +0 -0
  175. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/cli/__init__.py +0 -0
  176. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/cli/airt.py +0 -0
  177. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/cli/args.py +0 -0
  178. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/cli/capability.py +0 -0
  179. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/cli/dataset.py +0 -0
  180. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/cli/environment.py +0 -0
  181. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/cli/inference_model.py +0 -0
  182. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/cli/judge.py +0 -0
  183. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/cli/main.py +0 -0
  184. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/cli/model.py +0 -0
  185. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/cli/optimize.py +0 -0
  186. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/cli/runtime.py +0 -0
  187. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/cli/sandbox.py +0 -0
  188. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/cli/secret.py +0 -0
  189. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/cli/session.py +0 -0
  190. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/cli/shared.py +0 -0
  191. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/cli/templates/__init__.py +0 -0
  192. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/cli/templates/init/__init__.py +0 -0
  193. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/cli/templates/init/challenge/Dockerfile +0 -0
  194. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/cli/templates/init/docker-compose.yaml +0 -0
  195. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/cli/templates/init/provision.sh +0 -0
  196. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/cli/templates/init/solution.sh +0 -0
  197. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/cli/templates/init/task-remote.yaml.tmpl +0 -0
  198. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/cli/templates/init/task.yaml.tmpl +0 -0
  199. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/cli/templates/init/teardown.sh +0 -0
  200. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/cli/templates/init/verify.sh +0 -0
  201. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/cli/worlds.py +0 -0
  202. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/client/__init__.py +0 -0
  203. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/client/interactive.py +0 -0
  204. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/client/managed_client.py +0 -0
  205. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/client/models.py +0 -0
  206. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/client/transports.py +0 -0
  207. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/config.py +0 -0
  208. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/env.py +0 -0
  209. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/paths.py +0 -0
  210. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/server/__init__.py +0 -0
  211. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/server/auth.py +0 -0
  212. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/server/model_resolution.py +0 -0
  213. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/server/prompt.py +0 -0
  214. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/server/prompt_registry.py +0 -0
  215. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/server/runtime_events.py +0 -0
  216. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/server/session_hydrator.py +0 -0
  217. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/server/session_persistence.py +0 -0
  218. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/server/turn_coordinator.py +0 -0
  219. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/server/utils.py +0 -0
  220. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/server/websocket.py +0 -0
  221. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/server/worker_manager.py +0 -0
  222. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/__init__.py +0 -0
  223. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/auth_flow.py +0 -0
  224. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/command_dispatcher.py +0 -0
  225. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/commands.py +0 -0
  226. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/connection.py +0 -0
  227. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/error_handler.py +0 -0
  228. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/model_variants.py +0 -0
  229. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/profile_manager.py +0 -0
  230. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/runtime_cache.py +0 -0
  231. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/screens/auth.py +0 -0
  232. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/screens/base.py +0 -0
  233. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/screens/capability_docs.py +0 -0
  234. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/screens/connection_error.py +0 -0
  235. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/screens/console.py +0 -0
  236. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/screens/environments.py +0 -0
  237. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/screens/evaluations.py +0 -0
  238. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/screens/models.py +0 -0
  239. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/screens/raw_spans.py +0 -0
  240. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/screens/secrets.py +0 -0
  241. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/screens/sessions.py +0 -0
  242. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/screens/theme_showcase.py +0 -0
  243. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/screens/traces.py +0 -0
  244. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/screens/workspaces.py +0 -0
  245. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/sessions_manager.py +0 -0
  246. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/spans_reader.py +0 -0
  247. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/status_messages.py +0 -0
  248. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/theme.py +0 -0
  249. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/turn_coordinator.py +0 -0
  250. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/turn_lifecycle.py +0 -0
  251. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/turn_reducer.py +0 -0
  252. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/turn_state_phase.py +0 -0
  253. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/update_check.py +0 -0
  254. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/widgets/__init__.py +0 -0
  255. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/widgets/agent_dialog.py +0 -0
  256. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/widgets/agent_suggester.py +0 -0
  257. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/widgets/confirm_modal.py +0 -0
  258. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/widgets/context_bar.py +0 -0
  259. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/widgets/conversation.py +0 -0
  260. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/widgets/flash.py +0 -0
  261. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/widgets/header_bar.py +0 -0
  262. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/widgets/human_prompt.py +0 -0
  263. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/widgets/mention_overlay.py +0 -0
  264. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/widgets/message_queue.py +0 -0
  265. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/widgets/new_messages_pill.py +0 -0
  266. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/widgets/overlay_mixin.py +0 -0
  267. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/widgets/permission_prompt.py +0 -0
  268. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/widgets/profile_dialog.py +0 -0
  269. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/widgets/prompt_info.py +0 -0
  270. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/widgets/session_sidebar.py +0 -0
  271. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/widgets/skills_dialog.py +0 -0
  272. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/widgets/slash_overlay.py +0 -0
  273. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/widgets/status_bar.py +0 -0
  274. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/widgets/throbber.py +0 -0
  275. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/widgets/tool.py +0 -0
  276. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/widgets/tool_progress.py +0 -0
  277. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/widgets/tools_dialog.py +0 -0
  278. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/widgets/welcome.py +0 -0
  279. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/widgets/whoami.py +0 -0
  280. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/app/tui/wire_events.py +0 -0
  281. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/__init__.py +0 -0
  282. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/MAINTAINING.md +0 -0
  283. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/agents/dreadnode.md +0 -0
  284. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/capability.yaml +0 -0
  285. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/SKILL.md +0 -0
  286. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/capability-improvement.md +0 -0
  287. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/methodology-grounding.md +0 -0
  288. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/prior-art-audit.md +0 -0
  289. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/promoting-capabilities.md +0 -0
  290. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/quality-bar.md +0 -0
  291. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/agents.md +0 -0
  292. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/dependencies-and-checks.md +0 -0
  293. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/env-vars.md +0 -0
  294. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/events.md +0 -0
  295. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/flags.md +0 -0
  296. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/hooks.md +0 -0
  297. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/installing.md +0 -0
  298. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/manifest.md +0 -0
  299. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/overview.md +0 -0
  300. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/policies.md +0 -0
  301. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/publishing.md +0 -0
  302. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/quickstart.md +0 -0
  303. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/skills.md +0 -0
  304. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/tools.md +0 -0
  305. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/workers-reference.md +0 -0
  306. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/workers.md +0 -0
  307. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/tui/default-tools.md +0 -0
  308. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references-and-depth.md +0 -0
  309. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/runtime-default-capability.md +0 -0
  310. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/SKILL.md +0 -0
  311. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/INDEX.md +0 -0
  312. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/airt.md +0 -0
  313. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/capability.md +0 -0
  314. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/dataset.md +0 -0
  315. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/env.md +0 -0
  316. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/inference-model.md +0 -0
  317. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/main.md +0 -0
  318. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/model.md +0 -0
  319. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/optimize.md +0 -0
  320. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/overview.md +0 -0
  321. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/runtime.md +0 -0
  322. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/sandbox.md +0 -0
  323. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/secret.md +0 -0
  324. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/worlds.md +0 -0
  325. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/getting-started/authentication.md +0 -0
  326. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/SKILL.md +0 -0
  327. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/capabilities/installing.md +0 -0
  328. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/capabilities/overview.md +0 -0
  329. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/getting-started/authentication.md +0 -0
  330. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/getting-started/overview.md +0 -0
  331. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/overview.md +0 -0
  332. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/projects.md +0 -0
  333. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/users.md +0 -0
  334. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/workspaces.md +0 -0
  335. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/runtimes/configuration.md +0 -0
  336. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/runtimes/managing.md +0 -0
  337. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/runtimes/manifest-reference.md +0 -0
  338. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/runtimes/overview.md +0 -0
  339. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/runtimes/quickstart.md +0 -0
  340. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/runtimes/serve.md +0 -0
  341. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/sandboxes/overview.md +0 -0
  342. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/getting-started/SKILL.md +0 -0
  343. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/dreadnode/skills/research-capabilities/SKILL.md +0 -0
  344. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/self-improvement/.gitignore +0 -0
  345. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/self-improvement/capability.yaml +0 -0
  346. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/self-improvement/hooks/__init__.py +0 -0
  347. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/self-improvement/hooks/observer.py +0 -0
  348. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/self-improvement/self_improvement_lib/__init__.py +0 -0
  349. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/self-improvement/self_improvement_lib/classifier.py +0 -0
  350. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/self-improvement/self_improvement_lib/reflector_goal.py +0 -0
  351. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/self-improvement/self_improvement_lib/skill_io.py +0 -0
  352. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/self-improvement/skills-promoted/.gitkeep +0 -0
  353. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/self-improvement/skills-proposed/.gitkeep +0 -0
  354. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/self-improvement/tools/__init__.py +0 -0
  355. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/self-improvement/tools/reflector.py +0 -0
  356. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/builtin_capabilities/self-improvement/tools/skill_stats.py +0 -0
  357. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/capabilities/__init__.py +0 -0
  358. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/capabilities/capability.py +0 -0
  359. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/capabilities/flags.py +0 -0
  360. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/capabilities/install.py +0 -0
  361. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/capabilities/sync.py +0 -0
  362. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/capabilities/tool_rules.py +0 -0
  363. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/capabilities/worker.py +0 -0
  364. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/capabilities/worker_runner.py +0 -0
  365. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/core/__init__.py +0 -0
  366. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/core/conditions.py +0 -0
  367. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/core/discovery.py +0 -0
  368. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/core/environment.py +0 -0
  369. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/core/exceptions.py +0 -0
  370. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/core/execution.py +0 -0
  371. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/core/hook.py +0 -0
  372. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/core/judge.py +0 -0
  373. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/core/load.py +0 -0
  374. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/core/log.py +0 -0
  375. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/core/meta/__init__.py +0 -0
  376. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/core/meta/config.py +0 -0
  377. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/core/meta/context.py +0 -0
  378. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/core/meta/hydrate.py +0 -0
  379. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/core/meta/introspect.py +0 -0
  380. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/core/metric.py +0 -0
  381. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/core/object.py +0 -0
  382. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/core/scorer.py +0 -0
  383. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/core/serialization.py +0 -0
  384. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/core/stopping.py +0 -0
  385. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/core/task.py +0 -0
  386. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/core/templating.py +0 -0
  387. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/core/transforms.py +0 -0
  388. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/core/types/__init__.py +0 -0
  389. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/core/types/audio.py +0 -0
  390. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/core/types/base.py +0 -0
  391. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/core/types/common.py +0 -0
  392. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/core/types/image.py +0 -0
  393. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/core/types/object_3d.py +0 -0
  394. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/core/types/table.py +0 -0
  395. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/core/types/text.py +0 -0
  396. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/core/types/video.py +0 -0
  397. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/core/util.py +0 -0
  398. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/datasets/__init__.py +0 -0
  399. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/datasets/dataset.py +0 -0
  400. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/datasets/hf.py +0 -0
  401. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/datasets/local.py +0 -0
  402. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/evaluations/__init__.py +0 -0
  403. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/evaluations/console.py +0 -0
  404. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/evaluations/evaluation.py +0 -0
  405. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/evaluations/events.py +0 -0
  406. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/evaluations/format.py +0 -0
  407. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/evaluations/result.py +0 -0
  408. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/evaluations/sample.py +0 -0
  409. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/generators/__init__.py +0 -0
  410. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/generators/caching.py +0 -0
  411. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/generators/chat.py +0 -0
  412. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/generators/data.py +0 -0
  413. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/generators/exceptions.py +0 -0
  414. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/generators/generator/__init__.py +0 -0
  415. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/generators/generator/base.py +0 -0
  416. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/generators/generator/http.py +0 -0
  417. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/generators/generator/transformers_.py +0 -0
  418. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/generators/generator/vllm_.py +0 -0
  419. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/generators/message.py +0 -0
  420. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/generators/models.py +0 -0
  421. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/generators/parsing.py +0 -0
  422. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/generators/tokenizer/__init__.py +0 -0
  423. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/generators/tokenizer/base.py +0 -0
  424. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/generators/tokenizer/transformers_.py +0 -0
  425. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/generators/utils.py +0 -0
  426. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/judges/__init__.py +0 -0
  427. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/judges/outcome.py +0 -0
  428. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/judges/trajectory.py +0 -0
  429. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/judges/trajectory_tools.py +0 -0
  430. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/models/__init__.py +0 -0
  431. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/models/hf.py +0 -0
  432. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/models/local.py +0 -0
  433. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/models/model.py +0 -0
  434. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/optimization/__init__.py +0 -0
  435. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/optimization/adapters/__init__.py +0 -0
  436. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/optimization/adapters/_env_eval.py +0 -0
  437. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/optimization/adapters/agent.py +0 -0
  438. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/optimization/adapters/env.py +0 -0
  439. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/optimization/adapters/runtime.py +0 -0
  440. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/optimization/adapters/stack.py +0 -0
  441. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/optimization/api.py +0 -0
  442. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/optimization/backends/__init__.py +0 -0
  443. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/optimization/backends/base.py +0 -0
  444. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/optimization/backends/gepa.py +0 -0
  445. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/optimization/collectors.py +0 -0
  446. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/optimization/config.py +0 -0
  447. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/optimization/console.py +0 -0
  448. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/optimization/events.py +0 -0
  449. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/optimization/format.py +0 -0
  450. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/optimization/jobs.py +0 -0
  451. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/optimization/result.py +0 -0
  452. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/optimization/sampler.py +0 -0
  453. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/optimization/sampling.py +0 -0
  454. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/optimization/search.py +0 -0
  455. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/optimization/stopping.py +0 -0
  456. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/optimization/study.py +0 -0
  457. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/optimization/trial.py +0 -0
  458. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/packaging/__init__.py +0 -0
  459. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/packaging/loader.py +0 -0
  460. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/packaging/manifest.py +0 -0
  461. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/packaging/package.py +0 -0
  462. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/policies/__init__.py +0 -0
  463. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/policies/rubrics/process/default.yaml +0 -0
  464. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/py.typed +0 -0
  465. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/samplers/__init__.py +0 -0
  466. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/samplers/boundary.py +0 -0
  467. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/samplers/fuzzing.py +0 -0
  468. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/samplers/graph.py +0 -0
  469. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/samplers/grid.py +0 -0
  470. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/samplers/image.py +0 -0
  471. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/samplers/mapelites.py +0 -0
  472. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/samplers/optuna.py +0 -0
  473. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/samplers/random.py +0 -0
  474. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/samplers/registry.py +0 -0
  475. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/samplers/strategy.py +0 -0
  476. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/scorers/__init__.py +0 -0
  477. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/scorers/advanced_jailbreak_detection.py +0 -0
  478. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/scorers/agent_security.py +0 -0
  479. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/scorers/agentic.py +0 -0
  480. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/scorers/agentic_workflow.py +0 -0
  481. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/scorers/attack_outcome.py +0 -0
  482. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/scorers/classification.py +0 -0
  483. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/scorers/consistency.py +0 -0
  484. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/scorers/contains.py +0 -0
  485. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/scorers/cosine_sim.py +0 -0
  486. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/scorers/credentials.py +0 -0
  487. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/scorers/crucible.py +0 -0
  488. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/scorers/documentation_security.py +0 -0
  489. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/scorers/exfiltration_detection.py +0 -0
  490. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/scorers/format.py +0 -0
  491. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/scorers/harm.py +0 -0
  492. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/scorers/ide_security.py +0 -0
  493. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/scorers/image.py +0 -0
  494. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/scorers/json.py +0 -0
  495. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/scorers/judge_ensemble.py +0 -0
  496. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/scorers/length.py +0 -0
  497. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/scorers/lexical.py +0 -0
  498. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/scorers/mcp_security.py +0 -0
  499. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/scorers/memorization.py +0 -0
  500. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/scorers/multi_agent_security.py +0 -0
  501. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/scorers/pii.py +0 -0
  502. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/scorers/prompt_leak.py +0 -0
  503. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/scorers/readability.py +0 -0
  504. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/scorers/reasoning_security.py +0 -0
  505. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/scorers/sentiment.py +0 -0
  506. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/scorers/similarity.py +0 -0
  507. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/scorers/structural_detection.py +0 -0
  508. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/scorers/supply_chain_detection.py +0 -0
  509. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/storage/__init__.py +0 -0
  510. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/storage/providers.py +0 -0
  511. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/storage/session_store.py +0 -0
  512. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/storage/storage.py +0 -0
  513. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/tools/__init__.py +0 -0
  514. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/tools/_ripgrep.py +0 -0
  515. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/tools/apply_patch.py +0 -0
  516. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/tools/dreadnode_cli.py +0 -0
  517. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/tools/editing.py +0 -0
  518. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/tools/execute.py +0 -0
  519. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/tools/fetch.py +0 -0
  520. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/tools/glob.py +0 -0
  521. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/tools/grep.py +0 -0
  522. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/tools/interaction.py +0 -0
  523. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/tools/ls.py +0 -0
  524. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/tools/memory.py +0 -0
  525. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/tools/report.py +0 -0
  526. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/tools/task.py +0 -0
  527. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/tools/think.py +0 -0
  528. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/tools/todo.py +0 -0
  529. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/tools/trajectory_search.py +0 -0
  530. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/tools/web_extract.py +0 -0
  531. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/tools/web_search.py +0 -0
  532. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/tools/write.py +0 -0
  533. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/tracing/__init__.py +0 -0
  534. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/tracing/constants.py +0 -0
  535. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/tracing/convert.py +0 -0
  536. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/tracing/exporter.py +0 -0
  537. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/tracing/exporters.py +0 -0
  538. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/tracing/span.py +0 -0
  539. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/tracing/spans.py +0 -0
  540. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/tracing/trace_converter.py +0 -0
  541. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/__init__.py +0 -0
  542. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/_progress.py +0 -0
  543. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/base.py +0 -0
  544. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/dpo.py +0 -0
  545. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/env_rollouts.py +0 -0
  546. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/etl/__init__.py +0 -0
  547. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/etl/_common.py +0 -0
  548. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/etl/rl.py +0 -0
  549. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/etl/sft.py +0 -0
  550. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/etl/worlds.py +0 -0
  551. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/events.py +0 -0
  552. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/grpo.py +0 -0
  553. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/models.py +0 -0
  554. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/ppo.py +0 -0
  555. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/prime.py +0 -0
  556. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/ray/__init__.py +0 -0
  557. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/ray/async_trainer.py +0 -0
  558. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/ray/config.py +0 -0
  559. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/ray/coordinator.py +0 -0
  560. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/ray/distributed.py +0 -0
  561. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/ray/dpo.py +0 -0
  562. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/ray/experience.py +0 -0
  563. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/ray/fsdp2_learner.py +0 -0
  564. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/ray/inference.py +0 -0
  565. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/ray/learner.py +0 -0
  566. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/ray/multi_turn.py +0 -0
  567. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/ray/ppo.py +0 -0
  568. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/ray/reward_model.py +0 -0
  569. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/ray/rollout_env.py +0 -0
  570. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/ray/rollout_worker.py +0 -0
  571. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/ray/sft.py +0 -0
  572. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/ray/trainer.py +0 -0
  573. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/recipes.py +0 -0
  574. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/rewards/__init__.py +0 -0
  575. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/rewards/aggregator.py +0 -0
  576. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/rewards/functions.py +0 -0
  577. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/rewards/scorer_bridge.py +0 -0
  578. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/rewards/shaping.py +0 -0
  579. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/rewards/types.py +0 -0
  580. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/rollouts/__init__.py +0 -0
  581. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/rollouts/adapters.py +0 -0
  582. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/rollouts/agent_rollout.py +0 -0
  583. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/rollouts/orchestrator.py +0 -0
  584. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/rollouts/types.py +0 -0
  585. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/rollouts/worlds.py +0 -0
  586. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/serving/__init__.py +0 -0
  587. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/serving/vllm_client.py +0 -0
  588. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/sft.py +0 -0
  589. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/tinker/__init__.py +0 -0
  590. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/tinker/data.py +0 -0
  591. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/tinker/renderer.py +0 -0
  592. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/tinker/rl.py +0 -0
  593. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/tinker_sft.py +0 -0
  594. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/training/utils.py +0 -0
  595. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/transforms/__init__.py +0 -0
  596. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/transforms/advanced_jailbreak.py +0 -0
  597. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/transforms/adversarial_suffix.py +0 -0
  598. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/transforms/agent_skill.py +0 -0
  599. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/transforms/agentic_workflow.py +0 -0
  600. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/transforms/audio.py +0 -0
  601. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/transforms/backdoor_finetune.py +0 -0
  602. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/transforms/browser_agent_attacks.py +0 -0
  603. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/transforms/cipher.py +0 -0
  604. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/transforms/competitive_parity.py +0 -0
  605. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/transforms/constitutional.py +0 -0
  606. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/transforms/document.py +0 -0
  607. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/transforms/documentation_poison.py +0 -0
  608. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/transforms/encoding.py +0 -0
  609. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/transforms/exfiltration.py +0 -0
  610. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/transforms/flip_attack.py +0 -0
  611. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/transforms/guardrail_bypass.py +0 -0
  612. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/transforms/ide_injection.py +0 -0
  613. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/transforms/image.py +0 -0
  614. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/transforms/injection.py +0 -0
  615. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/transforms/json_tools.py +0 -0
  616. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/transforms/language.py +0 -0
  617. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/transforms/logic_bomb.py +0 -0
  618. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/transforms/mcp_attacks.py +0 -0
  619. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/transforms/multi_agent_attacks.py +0 -0
  620. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/transforms/multimodal_attacks.py +0 -0
  621. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/transforms/persuasion.py +0 -0
  622. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/transforms/perturbation.py +0 -0
  623. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/transforms/pii_extraction.py +0 -0
  624. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/transforms/pythonic_tools.py +0 -0
  625. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/transforms/rag_poisoning.py +0 -0
  626. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/transforms/reasoning_attacks.py +0 -0
  627. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/transforms/refine.py +0 -0
  628. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/transforms/response_steering.py +0 -0
  629. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/transforms/structural_exploits.py +0 -0
  630. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/transforms/stylistic.py +0 -0
  631. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/transforms/substitution.py +0 -0
  632. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/transforms/supply_chain.py +0 -0
  633. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/transforms/swap.py +0 -0
  634. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/transforms/system_prompt_extraction.py +0 -0
  635. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/transforms/text.py +0 -0
  636. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/transforms/video.py +0 -0
  637. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/transforms/xml_tools.py +0 -0
  638. {dreadnode-2.0.27 → dreadnode-2.0.29}/dreadnode/version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dreadnode
3
- Version: 2.0.27
3
+ Version: 2.0.29
4
4
  Summary: Dreadnode SDK
5
5
  Project-URL: Homepage, https://dreadnode.io
6
6
  Project-URL: Documentation, https://docs.dreadnode.io
@@ -0,0 +1,486 @@
1
+ """
2
+ MCP OAuth authentication support.
3
+
4
+ Provides file-based token storage, a localhost callback server for catching
5
+ OAuth redirects, a browser-opening redirect handler, and a factory that wires
6
+ those defaults onto the MCP SDK's :class:`OAuthClientProvider`.
7
+
8
+ Together they enable native HTTP MCP servers (e.g. Linear, Atlassian) to be
9
+ authenticated end-to-end by the Dreadnode runtime without going through the
10
+ ``npx mcp-remote`` stdio bridge.
11
+ """
12
+
13
+ import asyncio
14
+ import contextlib
15
+ import json
16
+ import os
17
+ import socket
18
+ import sys
19
+ import typing as t
20
+ import webbrowser
21
+ from collections.abc import Awaitable, Callable
22
+ from pathlib import Path
23
+ from urllib.parse import parse_qs, urlparse
24
+
25
+ from loguru import logger
26
+
27
+ if t.TYPE_CHECKING:
28
+ from mcp.client.auth.oauth2 import OAuthClientProvider, TokenStorage
29
+ from mcp.shared.auth import OAuthClientInformationFull, OAuthToken
30
+
31
+ from dreadnode.agents.mcp.config import OAuthConfig
32
+
33
+ DEFAULT_AUTH_PATH = Path.home() / ".dreadnode" / "mcp-auth.json"
34
+
35
+ # Default time (seconds) the local callback server waits for the user to
36
+ # complete the OAuth flow in their browser before giving up.
37
+ _DEFAULT_CALLBACK_TIMEOUT = 300.0
38
+
39
+
40
+ class MCPOAuthRequiredError(Exception):
41
+ """Raised when a connect would need to open a browser to complete OAuth
42
+ but the runtime isn't allowed to (a non-interactive / background connect).
43
+
44
+ Signals the lifecycle to classify the server as ``needs_auth`` and defer
45
+ the browser-open to a user-initiated Authenticate, rather than popping a
46
+ window during startup (CAP-MCP-010 — the runtime owns the browser-open
47
+ moment).
48
+ """
49
+
50
+
51
+ class FileTokenStorage:
52
+ """Persist OAuth tokens to disk, keyed by server URL.
53
+
54
+ File format (at ~/.dreadnode/mcp-auth.json, mode 0o600):
55
+ {
56
+ "https://api.example.com/mcp": {
57
+ "tokens": { ... },
58
+ "client_info": { ... }
59
+ }
60
+ }
61
+ """
62
+
63
+ def __init__(self, server_url: str, path: Path | None = None) -> None:
64
+ self._server_url = server_url
65
+ self._path = path or DEFAULT_AUTH_PATH
66
+
67
+ def _read_store(self) -> dict[str, t.Any]:
68
+ if not self._path.exists():
69
+ return {}
70
+ try:
71
+ return json.loads(self._path.read_text())
72
+ except (json.JSONDecodeError, OSError):
73
+ logger.warning("Corrupt MCP auth file at {}, starting fresh", self._path)
74
+ return {}
75
+
76
+ def _write_store(self, store: dict[str, t.Any]) -> None:
77
+ self._path.parent.mkdir(parents=True, exist_ok=True)
78
+ fd = os.open(self._path, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o600)
79
+ with os.fdopen(fd, "w") as f:
80
+ json.dump(store, f, indent=2)
81
+
82
+ def _get_entry(self) -> dict[str, t.Any]:
83
+ return self._read_store().get(self._server_url, {})
84
+
85
+ def has_tokens(self) -> bool:
86
+ """Synchronously report whether this server has stored OAuth tokens.
87
+
88
+ Used by the runtime to decide, *before* a background connect, whether
89
+ to wire up an OAuth provider at all. With no stored token a background
90
+ connect attaches no provider — a 401 then surfaces as ``needs_auth``
91
+ without any discovery/DCR traffic or browser-open. A small local file
92
+ read is cheap enough to do inline on the connect path.
93
+ """
94
+ return bool(self._get_entry().get("tokens"))
95
+
96
+ def _set_entry(self, entry: dict[str, t.Any]) -> None:
97
+ store = self._read_store()
98
+ store[self._server_url] = entry
99
+ self._write_store(store)
100
+
101
+ async def get_tokens(self) -> "OAuthToken | None":
102
+ from mcp.shared.auth import OAuthToken
103
+
104
+ entry = await asyncio.to_thread(self._get_entry)
105
+ data = entry.get("tokens")
106
+ if data is None:
107
+ return None
108
+ try:
109
+ return OAuthToken.model_validate(data)
110
+ except Exception:
111
+ logger.warning("Invalid stored tokens for {}", self._server_url)
112
+ return None
113
+
114
+ async def set_tokens(self, tokens: "OAuthToken") -> None:
115
+ def _update() -> None:
116
+ entry = self._get_entry()
117
+ entry["tokens"] = tokens.model_dump(mode="json", exclude_none=True)
118
+ self._set_entry(entry)
119
+
120
+ await asyncio.to_thread(_update)
121
+
122
+ async def get_client_info(self) -> "OAuthClientInformationFull | None":
123
+ from mcp.shared.auth import OAuthClientInformationFull
124
+
125
+ entry = await asyncio.to_thread(self._get_entry)
126
+ data = entry.get("client_info")
127
+ if data is None:
128
+ return None
129
+ try:
130
+ return OAuthClientInformationFull.model_validate(data)
131
+ except Exception:
132
+ logger.warning("Invalid stored client info for {}", self._server_url)
133
+ return None
134
+
135
+ async def set_client_info(self, client_info: "OAuthClientInformationFull") -> None:
136
+ def _update() -> None:
137
+ entry = self._get_entry()
138
+ entry["client_info"] = client_info.model_dump(mode="json", exclude_none=True)
139
+ self._set_entry(entry)
140
+
141
+ await asyncio.to_thread(_update)
142
+
143
+ async def clear(self) -> None:
144
+ """Remove this server's stored tokens + client_info from the file.
145
+
146
+ Targeted by server URL — other servers' entries are untouched.
147
+ Used by the user-initiated re-authenticate flow so a fresh OAuth
148
+ round-trip runs on the next connect without wiping the whole
149
+ cache (other authenticated capabilities keep working).
150
+ """
151
+
152
+ def _clear() -> None:
153
+ store = self._read_store()
154
+ if self._server_url in store:
155
+ del store[self._server_url]
156
+ self._write_store(store)
157
+
158
+ await asyncio.to_thread(_clear)
159
+
160
+
161
+ # --- Localhost OAuth callback server -----------------------------------------
162
+
163
+
164
+ _SUCCESS_HTML = (
165
+ b"<!doctype html><html><head><meta charset='utf-8'>"
166
+ b"<title>Dreadnode \xe2\x80\x94 Authentication complete</title>"
167
+ b"<style>body{font:14px/1.5 system-ui,sans-serif;max-width:32rem;"
168
+ b"margin:6rem auto;padding:0 1rem;color:#222;}h2{margin-bottom:.5rem}</style>"
169
+ b"</head><body><h2>Authentication complete \xe2\x9c\x93</h2>"
170
+ b"<p>You can close this tab and return to the Dreadnode TUI.</p>"
171
+ b"</body></html>"
172
+ )
173
+
174
+ _ERROR_HTML = (
175
+ b"<!doctype html><html><head><meta charset='utf-8'>"
176
+ b"<title>Dreadnode \xe2\x80\x94 Authentication failed</title></head>"
177
+ b"<body><h2>Authentication failed</h2>"
178
+ b"<p>The authorization server didn't return a code parameter. "
179
+ b"Return to the Dreadnode TUI and retry.</p></body></html>"
180
+ )
181
+
182
+
183
+ class LocalCallbackServer:
184
+ """One-shot HTTP server on a 127.0.0.1 ephemeral port for OAuth redirects.
185
+
186
+ Binds a socket eagerly in ``__init__`` so ``redirect_uri`` is known
187
+ before the OAuth flow needs it (the authorization server has to be
188
+ told the redirect URI at the start of the authorization request, well
189
+ before the user actually completes the flow). ``start()`` converts
190
+ the bound socket into a running ``asyncio.Server``; ``wait_for_callback()``
191
+ blocks until the redirect arrives, then tears the server down.
192
+
193
+ Single-use by design — a fresh instance per OAuth flow, no recycling.
194
+ The redirect URI is always ``http://127.0.0.1:<port>/callback``.
195
+ """
196
+
197
+ def __init__(
198
+ self,
199
+ *,
200
+ host: str = "127.0.0.1",
201
+ timeout: float = _DEFAULT_CALLBACK_TIMEOUT,
202
+ ) -> None:
203
+ self._host = host
204
+ self._timeout = timeout
205
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
206
+ sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
207
+ sock.bind((host, 0))
208
+ self._socket: socket.socket | None = sock
209
+ self._port: int = sock.getsockname()[1]
210
+ self._result: tuple[str, str | None] | None = None
211
+ self._error: str | None = None
212
+ self._received = asyncio.Event()
213
+ self._server: asyncio.Server | None = None
214
+
215
+ @property
216
+ def port(self) -> int:
217
+ return self._port
218
+
219
+ @property
220
+ def redirect_uri(self) -> str:
221
+ return f"http://{self._host}:{self._port}/callback"
222
+
223
+ async def start(self) -> None:
224
+ """Begin listening for the OAuth callback. Idempotent."""
225
+ if self._server is not None:
226
+ return
227
+ if self._socket is None:
228
+ msg = "LocalCallbackServer socket is already released — cannot start"
229
+ raise RuntimeError(msg)
230
+ self._server = await asyncio.start_server(self._handle_request, sock=self._socket)
231
+ # Server now owns the socket.
232
+ self._socket = None
233
+ logger.debug("OAuth callback server listening on {}", self.redirect_uri)
234
+
235
+ async def _handle_request(
236
+ self, reader: asyncio.StreamReader, writer: asyncio.StreamWriter
237
+ ) -> None:
238
+ try:
239
+ request_line = await reader.readline()
240
+ line = request_line.decode("latin-1", errors="replace").strip()
241
+ # Drain headers — we only need the request line.
242
+ while True:
243
+ hdr = await reader.readline()
244
+ if not hdr or hdr in (b"\r\n", b"\n"):
245
+ break
246
+
247
+ _method, _, rest = line.partition(" ")
248
+ target, _, _ = rest.partition(" ")
249
+ parsed = urlparse(target)
250
+ params = parse_qs(parsed.query)
251
+ code = params.get("code", [""])[0]
252
+ state_list = params.get("state")
253
+ state = state_list[0] if state_list else None
254
+ err = params.get("error", [""])[0]
255
+ err_desc = params.get("error_description", [""])[0]
256
+
257
+ if code:
258
+ self._result = (code, state)
259
+ self._received.set()
260
+ self._respond(writer, b"200 OK", _SUCCESS_HTML)
261
+ else:
262
+ self._error = err_desc or err or "missing 'code' parameter"
263
+ logger.warning("OAuth callback returned error: {}", self._error)
264
+ self._respond(writer, b"400 Bad Request", _ERROR_HTML)
265
+ self._received.set()
266
+ except Exception as exc:
267
+ logger.warning("OAuth callback handler error: {}", exc)
268
+ self._error = f"callback handler error: {exc}"
269
+ self._received.set()
270
+ finally:
271
+ with contextlib.suppress(Exception):
272
+ writer.close()
273
+ await writer.wait_closed()
274
+
275
+ @staticmethod
276
+ def _respond(writer: asyncio.StreamWriter, status: bytes, body: bytes) -> None:
277
+ writer.write(b"HTTP/1.1 " + status + b"\r\n")
278
+ writer.write(b"Content-Type: text/html; charset=utf-8\r\n")
279
+ writer.write(f"Content-Length: {len(body)}\r\n".encode())
280
+ writer.write(b"Connection: close\r\n\r\n")
281
+ writer.write(body)
282
+
283
+ async def wait_for_callback(self) -> tuple[str, str | None]:
284
+ """Block until the OAuth callback arrives. Returns (code, state).
285
+
286
+ Raises ``TimeoutError`` if the user doesn't complete the flow
287
+ within the configured timeout, or ``RuntimeError`` if the
288
+ callback arrived with an error parameter instead of a code.
289
+ Always tears the server down before returning.
290
+ """
291
+ try:
292
+ await asyncio.wait_for(self._received.wait(), timeout=self._timeout)
293
+ finally:
294
+ await self.aclose()
295
+ if self._result is not None:
296
+ return self._result
297
+ err = self._error or "no callback received"
298
+ raise RuntimeError(f"OAuth callback failed: {err}")
299
+
300
+ async def aclose(self) -> None:
301
+ """Shut down the server and release the socket. Idempotent."""
302
+ if self._server is not None:
303
+ self._server.close()
304
+ with contextlib.suppress(Exception):
305
+ await self._server.wait_closed()
306
+ self._server = None
307
+ if self._socket is not None:
308
+ with contextlib.suppress(Exception):
309
+ self._socket.close()
310
+ self._socket = None
311
+
312
+ def __del__(self) -> None: # pragma: no cover - best-effort GC cleanup
313
+ # Close the held socket if start() was never called (e.g. the
314
+ # OAuth flow never actually needed auth because a cached token
315
+ # was used). asyncio.Server cleanup is async and not reachable
316
+ # from __del__; rely on the loop's own teardown there.
317
+ if self._socket is not None:
318
+ with contextlib.suppress(Exception):
319
+ self._socket.close()
320
+
321
+
322
+ # --- Redirect handler --------------------------------------------------------
323
+
324
+
325
+ def _is_headless() -> bool:
326
+ """Best-effort detection of environments where opening a browser fails.
327
+
328
+ Honors the ``DREADNODE_HEADLESS`` opt-out for users who'd prefer to
329
+ complete OAuth manually even on a desktop machine. On Linux,
330
+ absence of ``DISPLAY`` and ``WAYLAND_DISPLAY`` is taken as a strong
331
+ signal (SSH, container, headless CI). On macOS/Windows we trust
332
+ ``webbrowser.open``'s return value instead.
333
+ """
334
+ if os.environ.get("DREADNODE_HEADLESS", "").strip().lower() in ("1", "true", "yes", "on"):
335
+ return True
336
+ if sys.platform.startswith("linux"):
337
+ if not os.environ.get("DISPLAY") and not os.environ.get("WAYLAND_DISPLAY"):
338
+ return True
339
+ return False
340
+
341
+
342
+ async def _browser_open_redirect_handler(url: str) -> None:
343
+ """Open the user's browser to *url*, or log it prominently if we can't.
344
+
345
+ The localhost callback server is the user's only way to deliver the
346
+ OAuth code back to us, so this handler must succeed *or* surface a
347
+ very clear manual fallback. ``DREADNODE_HEADLESS=1`` forces the
348
+ fallback path even on a desktop, which is useful for SSH sessions
349
+ that forward a port but no display.
350
+ """
351
+ if _is_headless():
352
+ logger.warning(
353
+ "MCP OAuth: browser disabled (DREADNODE_HEADLESS or no display). "
354
+ "Visit this URL to authorize:\n {}",
355
+ url,
356
+ )
357
+ return
358
+
359
+ try:
360
+ opened = webbrowser.open(url, new=1, autoraise=True)
361
+ except Exception as exc:
362
+ logger.debug("webbrowser.open raised: {}", exc)
363
+ opened = False
364
+
365
+ if opened:
366
+ logger.info("MCP OAuth: opened browser for authorization. Complete the flow to continue.")
367
+ else:
368
+ logger.warning(
369
+ "MCP OAuth: could not open a browser. Visit this URL manually:\n {}",
370
+ url,
371
+ )
372
+
373
+
374
+ async def _default_redirect_handler(url: str) -> None:
375
+ """Backwards-compat shim — log-only handler, kept for external callers
376
+ that explicitly pass it. New defaults use ``_browser_open_redirect_handler``.
377
+ """
378
+ logger.info("MCP OAuth: Visit this URL to authorize:\n {}", url)
379
+
380
+
381
+ async def _deferred_redirect_handler(url: str) -> None:
382
+ """Non-interactive redirect handler: refuse to open a browser.
383
+
384
+ Used by background connects (CAP-MCP-010). When the OAuth flow reaches
385
+ the point of opening the authorization URL, we raise instead — the
386
+ lifecycle classifies the server ``needs_auth`` and the user opens the
387
+ browser later via an explicit Authenticate. The URL is logged at debug
388
+ so it's recoverable for diagnostics, never auto-opened.
389
+ """
390
+ logger.debug("MCP OAuth: authorization required (deferred, non-interactive): {}", url)
391
+ raise MCPOAuthRequiredError(f"OAuth authorization required for {url}")
392
+
393
+
394
+ async def _deferred_callback_handler() -> tuple[str, str | None]:
395
+ """Non-interactive callback handler — never reached.
396
+
397
+ The deferred redirect handler raises before any callback is awaited;
398
+ this exists only to satisfy the provider's handler-pair contract.
399
+ """
400
+ raise MCPOAuthRequiredError("OAuth authorization required (non-interactive)")
401
+
402
+
403
+ def create_oauth_provider(
404
+ server_url: str,
405
+ config: OAuthConfig | None = None,
406
+ storage: "TokenStorage | None" = None,
407
+ redirect_handler: Callable[[str], Awaitable[None]] | None = None,
408
+ callback_handler: Callable[[], Awaitable[tuple[str, str | None]]] | None = None,
409
+ *,
410
+ interactive: bool = True,
411
+ callback_server: LocalCallbackServer | None = None,
412
+ ) -> "OAuthClientProvider":
413
+ """Build an :class:`OAuthClientProvider` wired with working defaults.
414
+
415
+ If neither ``redirect_handler`` nor ``callback_handler`` is provided,
416
+ the function wires the pair according to ``interactive``:
417
+
418
+ - ``interactive=True`` (user-initiated): spin up a
419
+ :class:`LocalCallbackServer`, open the user's browser (falling back to
420
+ a logged URL when headless), and block on the callback server until the
421
+ redirect arrives. The OAuth flow completes end-to-end.
422
+ - ``interactive=False`` (background/startup): never open a browser. A
423
+ valid stored token is still used/refreshed transparently; if the flow
424
+ would actually need to authorize, the deferred redirect handler raises
425
+ :class:`MCPOAuthRequiredError` so the runtime classifies ``needs_auth`` and
426
+ defers the browser to a user-initiated Authenticate (CAP-MCP-010).
427
+
428
+ Passing a custom ``redirect_handler`` *and* ``callback_handler``
429
+ bypasses the defaults entirely — useful for custom UIs (in-TUI
430
+ overlay, IDE picker, etc.).
431
+
432
+ Args:
433
+ server_url: The MCP server URL.
434
+ config: OAuth configuration. Uses defaults if None.
435
+ storage: Token storage. Defaults to :class:`FileTokenStorage`.
436
+ redirect_handler: Called with the authorization URL. Defaults per
437
+ ``interactive`` (browser-open, or deferred raise).
438
+ callback_handler: Called to retrieve ``(code, state)`` from the
439
+ redirect. Defaults to blocking on a localhost callback server.
440
+ interactive: Whether this connect may open a browser. Defaults True.
441
+ callback_server: Inject a pre-built callback server (testing).
442
+ """
443
+ from mcp.client.auth.oauth2 import OAuthClientProvider
444
+ from mcp.shared.auth import OAuthClientMetadata
445
+
446
+ config = config or OAuthConfig()
447
+
448
+ if storage is None:
449
+ storage = FileTokenStorage(server_url)
450
+
451
+ # If the caller didn't fully customize the handlers, set up the default
452
+ # pair. We do this even when only one side is overridden — that path is
453
+ # symmetric, both halves must come from the caller.
454
+ redirect_uris: list[t.Any] | None = None
455
+ if redirect_handler is None and callback_handler is None:
456
+ if not interactive:
457
+ # Background connect: stored tokens still work, but never pop a
458
+ # browser. The deferred handler raises if authorization is needed.
459
+ redirect_handler = _deferred_redirect_handler
460
+ callback_handler = _deferred_callback_handler
461
+ else:
462
+ if callback_server is None:
463
+ callback_server = LocalCallbackServer()
464
+ captured_server = callback_server # bind for closures + type narrowing
465
+
466
+ async def _redirect(url: str) -> None:
467
+ await captured_server.start()
468
+ await _browser_open_redirect_handler(url)
469
+
470
+ redirect_handler = _redirect
471
+ callback_handler = captured_server.wait_for_callback
472
+ redirect_uris = [captured_server.redirect_uri]
473
+
474
+ client_metadata = OAuthClientMetadata(
475
+ redirect_uris=redirect_uris,
476
+ client_name=config.client_name,
477
+ scope=config.scope,
478
+ )
479
+
480
+ return OAuthClientProvider(
481
+ server_url=server_url,
482
+ client_metadata=client_metadata,
483
+ storage=storage,
484
+ redirect_handler=redirect_handler or _default_redirect_handler,
485
+ callback_handler=callback_handler,
486
+ )