dreadnode 2.0.26__tar.gz → 2.0.27__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (634) hide show
  1. {dreadnode-2.0.26 → dreadnode-2.0.27}/PKG-INFO +1 -1
  2. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/api/client.py +6 -2
  3. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/app.py +4 -0
  4. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/model_manager.py +34 -1
  5. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/screens/models.py +145 -29
  6. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/widgets/context_bar.py +21 -2
  7. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/widgets/help_panel.py +16 -0
  8. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/getting-started/overview.md +2 -1
  9. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/getting-started/quickstart.md +4 -0
  10. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/packaging/task_validation.py +103 -17
  11. {dreadnode-2.0.26 → dreadnode-2.0.27}/pyproject.toml +1 -1
  12. {dreadnode-2.0.26 → dreadnode-2.0.27}/.gitignore +0 -0
  13. {dreadnode-2.0.26 → dreadnode-2.0.27}/LICENSE +0 -0
  14. {dreadnode-2.0.26 → dreadnode-2.0.27}/README.md +0 -0
  15. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/__init__.py +0 -0
  16. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/__main__.py +0 -0
  17. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/agents/__init__.py +0 -0
  18. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/agents/agent.py +0 -0
  19. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/agents/events.py +0 -0
  20. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/agents/exceptions.py +0 -0
  21. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/agents/format.py +0 -0
  22. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/agents/hooks.py +0 -0
  23. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/agents/judge.py +0 -0
  24. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/agents/mcp/__init__.py +0 -0
  25. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/agents/mcp/auth.py +0 -0
  26. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/agents/mcp/client.py +0 -0
  27. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/agents/mcp/config.py +0 -0
  28. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/agents/mcp/server.py +0 -0
  29. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/agents/process_judge.py +0 -0
  30. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/agents/reactions.py +0 -0
  31. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/agents/skills.py +0 -0
  32. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/agents/stopping.py +0 -0
  33. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/agents/subagent.py +0 -0
  34. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/agents/tool_resolution.py +0 -0
  35. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/agents/tools.py +0 -0
  36. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/agents/trajectory.py +0 -0
  37. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/__init__.py +0 -0
  38. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/adversarial_reasoning.py +0 -0
  39. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/advpromptier.py +0 -0
  40. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/alignment_faking.py +0 -0
  41. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/analogy_escalation.py +0 -0
  42. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/analytics/__init__.py +0 -0
  43. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/analytics/aggregator.py +0 -0
  44. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/analytics/classifier.py +0 -0
  45. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/analytics/compliance.py +0 -0
  46. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/analytics/engine.py +0 -0
  47. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/analytics/recommendations.py +0 -0
  48. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/analytics/types.py +0 -0
  49. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/aprt_progressive.py +0 -0
  50. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/assessment.py +0 -0
  51. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/attention_shifting.py +0 -0
  52. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/autodan_turbo.py +0 -0
  53. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/autoredteamer.py +0 -0
  54. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/beast.py +0 -0
  55. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/compliance/__init__.py +0 -0
  56. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/compliance/atlas.py +0 -0
  57. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/compliance/nist.py +0 -0
  58. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/compliance/owasp.py +0 -0
  59. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/compliance/owasp_agentic.py +0 -0
  60. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/compliance/saif.py +0 -0
  61. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/constants.py +0 -0
  62. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/cot_jailbreak.py +0 -0
  63. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/crescendo.py +0 -0
  64. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/data/__init__.py +0 -0
  65. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/data/assets/audio/adversarial_query.mp3 +0 -0
  66. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/data/assets/image/bomb.jpg +0 -0
  67. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/data/assets/image/meth.png +0 -0
  68. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/data/prompts/adversarial_benchmark_subset.csv +0 -0
  69. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/data/prompts/ai_safety.csv +0 -0
  70. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/data/rubrics/data_exfiltration.yaml +0 -0
  71. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/data/rubrics/goal_hijacking.yaml +0 -0
  72. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/data/rubrics/idor.yaml +0 -0
  73. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/data/rubrics/memory_poisoning.yaml +0 -0
  74. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/data/rubrics/privilege_escalation.yaml +0 -0
  75. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/data/rubrics/rce.yaml +0 -0
  76. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/data/rubrics/scope_creep.yaml +0 -0
  77. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/data/rubrics/tool_chaining.yaml +0 -0
  78. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/data/rubrics/tool_selection_safety.yaml +0 -0
  79. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/data/rubrics/unbounded_agency.yaml +0 -0
  80. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/data/rubrics/web_chatbot_security.yaml +0 -0
  81. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/data/templates/crescendo/variant_1.yaml +0 -0
  82. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/data/templates/crescendo/variant_2.yaml +0 -0
  83. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/data/templates/crescendo/variant_3.yaml +0 -0
  84. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/data/templates/crescendo/variant_4.yaml +0 -0
  85. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/data/templates/crescendo/variant_5.yaml +0 -0
  86. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/deep_inception.py +0 -0
  87. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/drattack.py +0 -0
  88. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/echo_chamber.py +0 -0
  89. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/events.py +0 -0
  90. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/genetic_persona.py +0 -0
  91. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/goat.py +0 -0
  92. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/goat_v2.py +0 -0
  93. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/gptfuzzer.py +0 -0
  94. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/humor_bypass.py +0 -0
  95. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/image.py +0 -0
  96. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/j2_meta.py +0 -0
  97. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/jbdistill.py +0 -0
  98. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/jbfuzz.py +0 -0
  99. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/lrm_autonomous.py +0 -0
  100. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/mapf.py +0 -0
  101. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/multimodal.py +0 -0
  102. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/nexus.py +0 -0
  103. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/pair.py +0 -0
  104. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/persona_hijack.py +0 -0
  105. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/prompt.py +0 -0
  106. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/quantization_safety.py +0 -0
  107. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/rainbow.py +0 -0
  108. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/refusal_aware.py +0 -0
  109. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/renellm.py +0 -0
  110. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/reporting/__init__.py +0 -0
  111. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/reporting/json_report.py +0 -0
  112. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/reporting/llm_summary.py +0 -0
  113. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/reporting/markdown.py +0 -0
  114. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/reward_hacking.py +0 -0
  115. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/salami_slicing.py +0 -0
  116. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/self_persuasion.py +0 -0
  117. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/siren.py +0 -0
  118. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/tap.py +0 -0
  119. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/templatefuzz.py +0 -0
  120. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/tmap_trajectory.py +0 -0
  121. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/trojail.py +0 -0
  122. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/airt/watermark_removal.py +0 -0
  123. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/__init__.py +0 -0
  124. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/api/__init__.py +0 -0
  125. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/api/models.py +0 -0
  126. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/cli/__init__.py +0 -0
  127. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/cli/airt.py +0 -0
  128. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/cli/args.py +0 -0
  129. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/cli/capability.py +0 -0
  130. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/cli/dataset.py +0 -0
  131. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/cli/environment.py +0 -0
  132. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/cli/evaluation.py +0 -0
  133. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/cli/inference_model.py +0 -0
  134. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/cli/judge.py +0 -0
  135. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/cli/main.py +0 -0
  136. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/cli/model.py +0 -0
  137. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/cli/optimize.py +0 -0
  138. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/cli/runtime.py +0 -0
  139. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/cli/sandbox.py +0 -0
  140. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/cli/secret.py +0 -0
  141. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/cli/session.py +0 -0
  142. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/cli/shared.py +0 -0
  143. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/cli/task.py +0 -0
  144. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/cli/templates/__init__.py +0 -0
  145. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/cli/templates/init/__init__.py +0 -0
  146. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/cli/templates/init/challenge/Dockerfile +0 -0
  147. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/cli/templates/init/docker-compose.yaml +0 -0
  148. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/cli/templates/init/provision.sh +0 -0
  149. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/cli/templates/init/solution.sh +0 -0
  150. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/cli/templates/init/task-remote.yaml.tmpl +0 -0
  151. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/cli/templates/init/task.yaml.tmpl +0 -0
  152. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/cli/templates/init/teardown.sh +0 -0
  153. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/cli/templates/init/verify.sh +0 -0
  154. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/cli/train.py +0 -0
  155. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/cli/worlds.py +0 -0
  156. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/client/__init__.py +0 -0
  157. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/client/interactive.py +0 -0
  158. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/client/managed_client.py +0 -0
  159. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/client/models.py +0 -0
  160. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/client/runtime_client.py +0 -0
  161. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/client/transports.py +0 -0
  162. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/config.py +0 -0
  163. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/env.py +0 -0
  164. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/main.py +0 -0
  165. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/model_catalog.py +0 -0
  166. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/paths.py +0 -0
  167. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/print_mode.py +0 -0
  168. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/server/__init__.py +0 -0
  169. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/server/app.py +0 -0
  170. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/server/auth.py +0 -0
  171. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/server/capability_manager.py +0 -0
  172. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/server/model_resolution.py +0 -0
  173. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/server/prompt.py +0 -0
  174. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/server/prompt_registry.py +0 -0
  175. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/server/runtime_events.py +0 -0
  176. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/server/session_hydrator.py +0 -0
  177. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/server/session_persistence.py +0 -0
  178. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/server/turn_coordinator.py +0 -0
  179. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/server/utils.py +0 -0
  180. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/server/websocket.py +0 -0
  181. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/server/worker_manager.py +0 -0
  182. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/__init__.py +0 -0
  183. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/auth_flow.py +0 -0
  184. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/capabilities_manager.py +0 -0
  185. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/command_dispatcher.py +0 -0
  186. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/commands.py +0 -0
  187. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/connection.py +0 -0
  188. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/dreadnode.tcss +0 -0
  189. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/error_handler.py +0 -0
  190. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/model_variants.py +0 -0
  191. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/profile_manager.py +0 -0
  192. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/runtime_cache.py +0 -0
  193. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/screen_router.py +0 -0
  194. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/screens/__init__.py +0 -0
  195. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/screens/auth.py +0 -0
  196. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/screens/base.py +0 -0
  197. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/screens/capabilities.py +0 -0
  198. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/screens/capability_docs.py +0 -0
  199. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/screens/connection_error.py +0 -0
  200. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/screens/console.py +0 -0
  201. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/screens/environments.py +0 -0
  202. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/screens/evaluations.py +0 -0
  203. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/screens/model_picker.py +0 -0
  204. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/screens/raw_spans.py +0 -0
  205. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/screens/runtimes.py +0 -0
  206. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/screens/sandboxes.py +0 -0
  207. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/screens/secrets.py +0 -0
  208. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/screens/services.py +0 -0
  209. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/screens/sessions.py +0 -0
  210. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/screens/theme_showcase.py +0 -0
  211. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/screens/traces.py +0 -0
  212. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/screens/workspaces.py +0 -0
  213. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/sessions_manager.py +0 -0
  214. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/spans_reader.py +0 -0
  215. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/status_messages.py +0 -0
  216. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/theme.py +0 -0
  217. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/tool_format.py +0 -0
  218. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/turn_coordinator.py +0 -0
  219. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/turn_lifecycle.py +0 -0
  220. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/turn_reducer.py +0 -0
  221. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/turn_state_phase.py +0 -0
  222. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/update_check.py +0 -0
  223. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/widgets/__init__.py +0 -0
  224. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/widgets/agent_dialog.py +0 -0
  225. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/widgets/agent_suggester.py +0 -0
  226. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/widgets/composer.py +0 -0
  227. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/widgets/confirm_modal.py +0 -0
  228. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/widgets/conversation.py +0 -0
  229. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/widgets/flash.py +0 -0
  230. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/widgets/header_bar.py +0 -0
  231. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/widgets/human_prompt.py +0 -0
  232. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/widgets/mention_overlay.py +0 -0
  233. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/widgets/message_queue.py +0 -0
  234. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/widgets/new_messages_pill.py +0 -0
  235. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/widgets/overlay_mixin.py +0 -0
  236. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/widgets/permission_prompt.py +0 -0
  237. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/widgets/profile_dialog.py +0 -0
  238. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/widgets/prompt_info.py +0 -0
  239. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/widgets/rewind_picker.py +0 -0
  240. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/widgets/session_sidebar.py +0 -0
  241. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/widgets/skills_dialog.py +0 -0
  242. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/widgets/slash_overlay.py +0 -0
  243. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/widgets/status_bar.py +0 -0
  244. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/widgets/throbber.py +0 -0
  245. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/widgets/tool.py +0 -0
  246. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/widgets/tool_progress.py +0 -0
  247. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/widgets/tools_dialog.py +0 -0
  248. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/widgets/welcome.py +0 -0
  249. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/widgets/whoami.py +0 -0
  250. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/app/tui/wire_events.py +0 -0
  251. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/__init__.py +0 -0
  252. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/MAINTAINING.md +0 -0
  253. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/agents/dreadnode.md +0 -0
  254. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/capability.yaml +0 -0
  255. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/SKILL.md +0 -0
  256. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/capability-improvement.md +0 -0
  257. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/methodology-grounding.md +0 -0
  258. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/prior-art-audit.md +0 -0
  259. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/promoting-capabilities.md +0 -0
  260. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/quality-bar.md +0 -0
  261. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/INDEX.md +0 -0
  262. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/agents.md +0 -0
  263. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/dependencies-and-checks.md +0 -0
  264. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/env-vars.md +0 -0
  265. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/events.md +0 -0
  266. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/flags.md +0 -0
  267. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/hooks.md +0 -0
  268. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/installing.md +0 -0
  269. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/manifest.md +0 -0
  270. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/mcp-servers.md +0 -0
  271. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/overview.md +0 -0
  272. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/policies.md +0 -0
  273. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/publishing.md +0 -0
  274. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/quickstart.md +0 -0
  275. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/skills.md +0 -0
  276. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/tools.md +0 -0
  277. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/workers-reference.md +0 -0
  278. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/workers.md +0 -0
  279. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/writing-skills.md +0 -0
  280. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/guides/capability-optimization-loop.md +0 -0
  281. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/sdk/agents.md +0 -0
  282. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/sdk/capabilities.md +0 -0
  283. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/tui/default-tools.md +0 -0
  284. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references-and-depth.md +0 -0
  285. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/runtime-default-capability.md +0 -0
  286. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/SKILL.md +0 -0
  287. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/INDEX.md +0 -0
  288. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/airt.md +0 -0
  289. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/capability.md +0 -0
  290. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/dataset.md +0 -0
  291. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/env.md +0 -0
  292. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/evaluation.md +0 -0
  293. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/inference-model.md +0 -0
  294. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/main.md +0 -0
  295. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/model.md +0 -0
  296. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/optimize.md +0 -0
  297. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/overview.md +0 -0
  298. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/runtime.md +0 -0
  299. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/sandbox.md +0 -0
  300. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/secret.md +0 -0
  301. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/task.md +0 -0
  302. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/train.md +0 -0
  303. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/worlds.md +0 -0
  304. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/getting-started/authentication.md +0 -0
  305. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/SKILL.md +0 -0
  306. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/INDEX.md +0 -0
  307. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/capabilities/installing.md +0 -0
  308. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/capabilities/overview.md +0 -0
  309. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/getting-started/authentication.md +0 -0
  310. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/chat-models.md +0 -0
  311. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/credits.md +0 -0
  312. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/organizations.md +0 -0
  313. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/overview.md +0 -0
  314. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/projects.md +0 -0
  315. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/secrets.md +0 -0
  316. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/settings.md +0 -0
  317. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/users.md +0 -0
  318. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/workspaces.md +0 -0
  319. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/runtimes/configuration.md +0 -0
  320. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/runtimes/managing.md +0 -0
  321. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/runtimes/manifest-reference.md +0 -0
  322. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/runtimes/overview.md +0 -0
  323. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/runtimes/quickstart.md +0 -0
  324. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/runtimes/serve.md +0 -0
  325. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/sandboxes/environment-lifecycle.md +0 -0
  326. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/sandboxes/inspecting.md +0 -0
  327. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/sandboxes/overview.md +0 -0
  328. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/getting-started/SKILL.md +0 -0
  329. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/dreadnode/skills/research-capabilities/SKILL.md +0 -0
  330. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/self-improvement/.gitignore +0 -0
  331. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/self-improvement/capability.yaml +0 -0
  332. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/self-improvement/hooks/__init__.py +0 -0
  333. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/self-improvement/hooks/observer.py +0 -0
  334. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/self-improvement/self_improvement_lib/__init__.py +0 -0
  335. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/self-improvement/self_improvement_lib/classifier.py +0 -0
  336. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/self-improvement/self_improvement_lib/reflector_goal.py +0 -0
  337. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/self-improvement/self_improvement_lib/skill_io.py +0 -0
  338. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/self-improvement/skills-promoted/.gitkeep +0 -0
  339. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/self-improvement/skills-proposed/.gitkeep +0 -0
  340. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/self-improvement/tools/__init__.py +0 -0
  341. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/self-improvement/tools/reflector.py +0 -0
  342. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/builtin_capabilities/self-improvement/tools/skill_stats.py +0 -0
  343. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/capabilities/__init__.py +0 -0
  344. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/capabilities/capability.py +0 -0
  345. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/capabilities/flags.py +0 -0
  346. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/capabilities/install.py +0 -0
  347. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/capabilities/loader.py +0 -0
  348. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/capabilities/sync.py +0 -0
  349. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/capabilities/tool_rules.py +0 -0
  350. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/capabilities/types.py +0 -0
  351. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/capabilities/worker.py +0 -0
  352. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/capabilities/worker_runner.py +0 -0
  353. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/core/__init__.py +0 -0
  354. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/core/conditions.py +0 -0
  355. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/core/discovery.py +0 -0
  356. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/core/environment.py +0 -0
  357. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/core/exceptions.py +0 -0
  358. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/core/execution.py +0 -0
  359. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/core/hook.py +0 -0
  360. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/core/judge.py +0 -0
  361. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/core/load.py +0 -0
  362. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/core/log.py +0 -0
  363. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/core/meta/__init__.py +0 -0
  364. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/core/meta/config.py +0 -0
  365. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/core/meta/context.py +0 -0
  366. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/core/meta/hydrate.py +0 -0
  367. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/core/meta/introspect.py +0 -0
  368. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/core/metric.py +0 -0
  369. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/core/object.py +0 -0
  370. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/core/scorer.py +0 -0
  371. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/core/serialization.py +0 -0
  372. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/core/stopping.py +0 -0
  373. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/core/task.py +0 -0
  374. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/core/templating.py +0 -0
  375. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/core/transforms.py +0 -0
  376. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/core/types/__init__.py +0 -0
  377. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/core/types/audio.py +0 -0
  378. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/core/types/base.py +0 -0
  379. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/core/types/common.py +0 -0
  380. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/core/types/image.py +0 -0
  381. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/core/types/object_3d.py +0 -0
  382. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/core/types/table.py +0 -0
  383. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/core/types/text.py +0 -0
  384. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/core/types/video.py +0 -0
  385. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/core/util.py +0 -0
  386. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/datasets/__init__.py +0 -0
  387. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/datasets/dataset.py +0 -0
  388. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/datasets/hf.py +0 -0
  389. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/datasets/local.py +0 -0
  390. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/evaluations/__init__.py +0 -0
  391. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/evaluations/console.py +0 -0
  392. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/evaluations/evaluation.py +0 -0
  393. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/evaluations/events.py +0 -0
  394. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/evaluations/format.py +0 -0
  395. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/evaluations/result.py +0 -0
  396. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/evaluations/sample.py +0 -0
  397. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/generators/__init__.py +0 -0
  398. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/generators/caching.py +0 -0
  399. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/generators/chat.py +0 -0
  400. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/generators/data.py +0 -0
  401. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/generators/exceptions.py +0 -0
  402. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/generators/generator/__init__.py +0 -0
  403. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/generators/generator/base.py +0 -0
  404. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/generators/generator/http.py +0 -0
  405. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/generators/generator/litellm_.py +0 -0
  406. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/generators/generator/transformers_.py +0 -0
  407. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/generators/generator/vllm_.py +0 -0
  408. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/generators/message.py +0 -0
  409. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/generators/models.py +0 -0
  410. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/generators/parsing.py +0 -0
  411. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/generators/tokenizer/__init__.py +0 -0
  412. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/generators/tokenizer/base.py +0 -0
  413. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/generators/tokenizer/transformers_.py +0 -0
  414. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/generators/utils.py +0 -0
  415. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/judges/__init__.py +0 -0
  416. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/judges/outcome.py +0 -0
  417. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/judges/trajectory.py +0 -0
  418. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/judges/trajectory_tools.py +0 -0
  419. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/models/__init__.py +0 -0
  420. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/models/hf.py +0 -0
  421. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/models/local.py +0 -0
  422. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/models/model.py +0 -0
  423. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/optimization/__init__.py +0 -0
  424. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/optimization/adapters/__init__.py +0 -0
  425. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/optimization/adapters/_env_eval.py +0 -0
  426. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/optimization/adapters/agent.py +0 -0
  427. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/optimization/adapters/env.py +0 -0
  428. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/optimization/adapters/runtime.py +0 -0
  429. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/optimization/adapters/stack.py +0 -0
  430. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/optimization/api.py +0 -0
  431. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/optimization/backends/__init__.py +0 -0
  432. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/optimization/backends/base.py +0 -0
  433. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/optimization/backends/gepa.py +0 -0
  434. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/optimization/collectors.py +0 -0
  435. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/optimization/config.py +0 -0
  436. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/optimization/console.py +0 -0
  437. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/optimization/events.py +0 -0
  438. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/optimization/format.py +0 -0
  439. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/optimization/jobs.py +0 -0
  440. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/optimization/result.py +0 -0
  441. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/optimization/sampler.py +0 -0
  442. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/optimization/sampling.py +0 -0
  443. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/optimization/search.py +0 -0
  444. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/optimization/stopping.py +0 -0
  445. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/optimization/study.py +0 -0
  446. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/optimization/trial.py +0 -0
  447. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/packaging/__init__.py +0 -0
  448. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/packaging/loader.py +0 -0
  449. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/packaging/manifest.py +0 -0
  450. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/packaging/oci.py +0 -0
  451. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/packaging/package.py +0 -0
  452. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/policies/__init__.py +0 -0
  453. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/policies/guard.py +0 -0
  454. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/policies/rubrics/process/default.yaml +0 -0
  455. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/py.typed +0 -0
  456. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/samplers/__init__.py +0 -0
  457. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/samplers/boundary.py +0 -0
  458. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/samplers/fuzzing.py +0 -0
  459. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/samplers/graph.py +0 -0
  460. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/samplers/grid.py +0 -0
  461. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/samplers/image.py +0 -0
  462. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/samplers/mapelites.py +0 -0
  463. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/samplers/optuna.py +0 -0
  464. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/samplers/random.py +0 -0
  465. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/samplers/registry.py +0 -0
  466. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/samplers/strategy.py +0 -0
  467. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/scorers/__init__.py +0 -0
  468. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/scorers/advanced_jailbreak_detection.py +0 -0
  469. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/scorers/agent_security.py +0 -0
  470. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/scorers/agentic.py +0 -0
  471. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/scorers/agentic_workflow.py +0 -0
  472. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/scorers/attack_outcome.py +0 -0
  473. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/scorers/classification.py +0 -0
  474. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/scorers/consistency.py +0 -0
  475. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/scorers/contains.py +0 -0
  476. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/scorers/cosine_sim.py +0 -0
  477. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/scorers/credentials.py +0 -0
  478. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/scorers/crucible.py +0 -0
  479. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/scorers/documentation_security.py +0 -0
  480. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/scorers/exfiltration_detection.py +0 -0
  481. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/scorers/format.py +0 -0
  482. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/scorers/harm.py +0 -0
  483. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/scorers/ide_security.py +0 -0
  484. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/scorers/image.py +0 -0
  485. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/scorers/json.py +0 -0
  486. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/scorers/judge.py +0 -0
  487. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/scorers/judge_ensemble.py +0 -0
  488. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/scorers/length.py +0 -0
  489. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/scorers/lexical.py +0 -0
  490. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/scorers/mcp_security.py +0 -0
  491. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/scorers/memorization.py +0 -0
  492. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/scorers/multi_agent_security.py +0 -0
  493. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/scorers/pii.py +0 -0
  494. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/scorers/prompt_leak.py +0 -0
  495. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/scorers/readability.py +0 -0
  496. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/scorers/reasoning_security.py +0 -0
  497. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/scorers/sentiment.py +0 -0
  498. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/scorers/similarity.py +0 -0
  499. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/scorers/structural_detection.py +0 -0
  500. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/scorers/supply_chain_detection.py +0 -0
  501. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/storage/__init__.py +0 -0
  502. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/storage/providers.py +0 -0
  503. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/storage/session_store.py +0 -0
  504. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/storage/storage.py +0 -0
  505. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/tools/__init__.py +0 -0
  506. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/tools/_ripgrep.py +0 -0
  507. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/tools/apply_patch.py +0 -0
  508. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/tools/dreadnode_cli.py +0 -0
  509. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/tools/editing.py +0 -0
  510. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/tools/execute.py +0 -0
  511. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/tools/fetch.py +0 -0
  512. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/tools/glob.py +0 -0
  513. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/tools/grep.py +0 -0
  514. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/tools/interaction.py +0 -0
  515. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/tools/ls.py +0 -0
  516. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/tools/memory.py +0 -0
  517. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/tools/read.py +0 -0
  518. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/tools/report.py +0 -0
  519. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/tools/task.py +0 -0
  520. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/tools/think.py +0 -0
  521. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/tools/todo.py +0 -0
  522. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/tools/trajectory_search.py +0 -0
  523. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/tools/web_extract.py +0 -0
  524. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/tools/web_search.py +0 -0
  525. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/tools/write.py +0 -0
  526. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/tracing/__init__.py +0 -0
  527. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/tracing/constants.py +0 -0
  528. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/tracing/convert.py +0 -0
  529. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/tracing/exporter.py +0 -0
  530. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/tracing/exporters.py +0 -0
  531. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/tracing/span.py +0 -0
  532. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/tracing/spans.py +0 -0
  533. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/tracing/trace_converter.py +0 -0
  534. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/__init__.py +0 -0
  535. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/_progress.py +0 -0
  536. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/base.py +0 -0
  537. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/dpo.py +0 -0
  538. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/env_rollouts.py +0 -0
  539. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/etl/__init__.py +0 -0
  540. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/etl/_common.py +0 -0
  541. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/etl/rl.py +0 -0
  542. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/etl/sft.py +0 -0
  543. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/etl/worlds.py +0 -0
  544. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/events.py +0 -0
  545. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/grpo.py +0 -0
  546. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/jobs.py +0 -0
  547. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/models.py +0 -0
  548. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/ppo.py +0 -0
  549. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/prime.py +0 -0
  550. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/ray/__init__.py +0 -0
  551. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/ray/async_trainer.py +0 -0
  552. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/ray/config.py +0 -0
  553. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/ray/coordinator.py +0 -0
  554. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/ray/distributed.py +0 -0
  555. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/ray/dpo.py +0 -0
  556. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/ray/experience.py +0 -0
  557. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/ray/fsdp2_learner.py +0 -0
  558. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/ray/inference.py +0 -0
  559. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/ray/learner.py +0 -0
  560. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/ray/multi_turn.py +0 -0
  561. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/ray/ppo.py +0 -0
  562. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/ray/reward_model.py +0 -0
  563. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/ray/rollout_env.py +0 -0
  564. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/ray/rollout_worker.py +0 -0
  565. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/ray/sft.py +0 -0
  566. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/ray/trainer.py +0 -0
  567. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/recipes.py +0 -0
  568. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/rewards/__init__.py +0 -0
  569. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/rewards/aggregator.py +0 -0
  570. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/rewards/functions.py +0 -0
  571. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/rewards/scorer_bridge.py +0 -0
  572. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/rewards/shaping.py +0 -0
  573. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/rewards/types.py +0 -0
  574. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/rollouts/__init__.py +0 -0
  575. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/rollouts/adapters.py +0 -0
  576. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/rollouts/agent_rollout.py +0 -0
  577. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/rollouts/orchestrator.py +0 -0
  578. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/rollouts/types.py +0 -0
  579. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/rollouts/worlds.py +0 -0
  580. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/serving/__init__.py +0 -0
  581. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/serving/vllm_client.py +0 -0
  582. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/sft.py +0 -0
  583. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/tinker/__init__.py +0 -0
  584. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/tinker/config.py +0 -0
  585. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/tinker/data.py +0 -0
  586. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/tinker/renderer.py +0 -0
  587. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/tinker/rl.py +0 -0
  588. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/tinker/trainer.py +0 -0
  589. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/tinker_sft.py +0 -0
  590. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/training/utils.py +0 -0
  591. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/transforms/__init__.py +0 -0
  592. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/transforms/advanced_jailbreak.py +0 -0
  593. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/transforms/adversarial_suffix.py +0 -0
  594. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/transforms/agent_skill.py +0 -0
  595. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/transforms/agentic_workflow.py +0 -0
  596. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/transforms/audio.py +0 -0
  597. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/transforms/backdoor_finetune.py +0 -0
  598. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/transforms/browser_agent_attacks.py +0 -0
  599. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/transforms/cipher.py +0 -0
  600. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/transforms/competitive_parity.py +0 -0
  601. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/transforms/constitutional.py +0 -0
  602. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/transforms/document.py +0 -0
  603. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/transforms/documentation_poison.py +0 -0
  604. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/transforms/encoding.py +0 -0
  605. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/transforms/exfiltration.py +0 -0
  606. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/transforms/flip_attack.py +0 -0
  607. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/transforms/guardrail_bypass.py +0 -0
  608. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/transforms/ide_injection.py +0 -0
  609. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/transforms/image.py +0 -0
  610. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/transforms/injection.py +0 -0
  611. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/transforms/json_tools.py +0 -0
  612. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/transforms/language.py +0 -0
  613. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/transforms/logic_bomb.py +0 -0
  614. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/transforms/mcp_attacks.py +0 -0
  615. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/transforms/multi_agent_attacks.py +0 -0
  616. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/transforms/multimodal_attacks.py +0 -0
  617. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/transforms/persuasion.py +0 -0
  618. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/transforms/perturbation.py +0 -0
  619. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/transforms/pii_extraction.py +0 -0
  620. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/transforms/pythonic_tools.py +0 -0
  621. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/transforms/rag_poisoning.py +0 -0
  622. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/transforms/reasoning_attacks.py +0 -0
  623. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/transforms/refine.py +0 -0
  624. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/transforms/response_steering.py +0 -0
  625. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/transforms/structural_exploits.py +0 -0
  626. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/transforms/stylistic.py +0 -0
  627. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/transforms/substitution.py +0 -0
  628. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/transforms/supply_chain.py +0 -0
  629. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/transforms/swap.py +0 -0
  630. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/transforms/system_prompt_extraction.py +0 -0
  631. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/transforms/text.py +0 -0
  632. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/transforms/video.py +0 -0
  633. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/transforms/xml_tools.py +0 -0
  634. {dreadnode-2.0.26 → dreadnode-2.0.27}/dreadnode/version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dreadnode
3
- Version: 2.0.26
3
+ Version: 2.0.27
4
4
  Summary: Dreadnode SDK
5
5
  Project-URL: Homepage, https://dreadnode.io
6
6
  Project-URL: Documentation, https://docs.dreadnode.io
@@ -363,9 +363,13 @@ class ApiClient:
363
363
  response = self.request("GET", "/user/preferences", params=params)
364
364
  return t.cast("dict[str, t.Any]", response.json())
365
365
 
366
- def provision_inference_key(self, org_key: str) -> dict[str, t.Any]:
366
+ def provision_inference_key(self, org_key: str, client_id: str) -> dict[str, t.Any]:
367
367
  """POST /api/v1/org/{org}/inference/keys - Provision a litellm virtual key."""
368
- response = self.request("POST", f"/org/{org_key}/inference/keys")
368
+ response = self.request(
369
+ "POST",
370
+ f"/org/{org_key}/inference/keys",
371
+ json_data={"client_id": client_id},
372
+ )
369
373
  return t.cast("dict[str, t.Any]", response.json())
370
374
 
371
375
  # =========================================================================
@@ -257,6 +257,7 @@ class _AppModelUiHost:
257
257
  platform_models: list[dict[str, t.Any]],
258
258
  byok_models: list[dict[str, t.Any]],
259
259
  current_model: str,
260
+ inference_credits_per_dollar: int | None,
260
261
  access_restricted: bool,
261
262
  search_models: t.Callable[..., t.Any],
262
263
  on_selected: t.Callable[[str | None], None],
@@ -268,6 +269,7 @@ class _AppModelUiHost:
268
269
  platform_models=platform_models,
269
270
  byok_models=byok_models,
270
271
  current_model=current_model,
272
+ inference_credits_per_dollar=inference_credits_per_dollar,
271
273
  access_restricted=access_restricted,
272
274
  search_models=search_models,
273
275
  ),
@@ -280,6 +282,7 @@ class _AppModelUiHost:
280
282
  platform_models: list[dict[str, t.Any]],
281
283
  byok_models: list[dict[str, t.Any]],
282
284
  current_model: str,
285
+ inference_credits_per_dollar: int | None,
283
286
  access_restricted: bool,
284
287
  ) -> None:
285
288
  from dreadnode.app.tui.screens import ModelBrowserScreen
@@ -291,6 +294,7 @@ class _AppModelUiHost:
291
294
  platform_models=platform_models,
292
295
  byok_models=byok_models,
293
296
  current_model=current_model,
297
+ inference_credits_per_dollar=inference_credits_per_dollar,
294
298
  access_restricted=access_restricted,
295
299
  )
296
300
  break
@@ -9,6 +9,7 @@ import typing as t
9
9
  from dataclasses import dataclass, field
10
10
  from datetime import UTC, datetime, timedelta
11
11
  from pathlib import Path
12
+ from uuid import uuid4
12
13
 
13
14
  import httpx
14
15
  from loguru import logger
@@ -25,6 +26,7 @@ LITELLM_REFRESH_WINDOW = timedelta(minutes=5)
25
26
  PROXY_MODELS_CACHE_FILE = Path.home() / ".dreadnode" / "proxy-models.json"
26
27
  MODEL_BROWSER_FEATURED_LIMIT = 12
27
28
  MODEL_BROWSER_SEARCH_LIMIT = 50
29
+ DEFAULT_INFERENCE_CREDITS_PER_DOLLAR = 1000
28
30
 
29
31
 
30
32
  @dataclass(slots=True)
@@ -32,6 +34,7 @@ class ModelCatalogState:
32
34
  platform_models: list[dict[str, t.Any]] = field(default_factory=list)
33
35
  user_model_ids: list[str] = field(default_factory=list)
34
36
  preference_platform_model_ids: list[str] = field(default_factory=list)
37
+ inference_credits_per_dollar: int | None = None
35
38
  access_restricted: bool = False
36
39
  proxy_model_ids_synced: bool = False
37
40
  litellm_key_expires_at: datetime | None = None
@@ -72,6 +75,7 @@ class ModelUiHost(t.Protocol):
72
75
  platform_models: list[dict[str, t.Any]],
73
76
  byok_models: list[dict[str, t.Any]],
74
77
  current_model: str,
78
+ inference_credits_per_dollar: int | None,
75
79
  access_restricted: bool,
76
80
  search_models: t.Callable[..., t.Any],
77
81
  on_selected: t.Callable[[str | None], None],
@@ -83,6 +87,7 @@ class ModelUiHost(t.Protocol):
83
87
  platform_models: list[dict[str, t.Any]],
84
88
  byok_models: list[dict[str, t.Any]],
85
89
  current_model: str,
90
+ inference_credits_per_dollar: int | None,
86
91
  access_restricted: bool,
87
92
  ) -> None: ...
88
93
 
@@ -122,6 +127,7 @@ class ModelManager:
122
127
  self._runner = runner
123
128
  self._notifier = notifier
124
129
  self._actions = actions
130
+ self._tui_client_id = uuid4().hex
125
131
 
126
132
  def open_model_picker(self) -> None:
127
133
  """Show the inline model picker overlay."""
@@ -152,6 +158,7 @@ class ModelManager:
152
158
  platform_models=list(self._state.platform_models),
153
159
  byok_models=self.browser_seed_models(),
154
160
  current_model=self._context.current_model(),
161
+ inference_credits_per_dollar=self._state.inference_credits_per_dollar,
155
162
  access_restricted=self._state.access_restricted,
156
163
  search_models=self.search_model_browser_models,
157
164
  on_selected=self.apply_model_selection,
@@ -253,6 +260,7 @@ class ModelManager:
253
260
  platform_models=list(self._state.platform_models),
254
261
  byok_models=self.browser_seed_models(),
255
262
  current_model=self._context.current_model(),
263
+ inference_credits_per_dollar=self._state.inference_credits_per_dollar,
256
264
  access_restricted=self._state.access_restricted,
257
265
  )
258
266
 
@@ -281,12 +289,25 @@ class ModelManager:
281
289
  self._state.platform_models = []
282
290
  self._state.user_model_ids = []
283
291
  self._state.preference_platform_model_ids = []
292
+ self._state.inference_credits_per_dollar = None
284
293
  self._state.access_restricted = False
285
294
  self._state.proxy_model_ids_synced = False
286
295
  self._state.litellm_key_expires_at = None
287
296
  os.environ.pop(DREADNODE_LLM_BASE_ENV, None)
288
297
  os.environ.pop(DREADNODE_LLM_API_KEY_ENV, None)
289
298
 
299
+ @staticmethod
300
+ def parse_inference_credits_per_dollar(value: t.Any) -> int | None:
301
+ if value is None:
302
+ return DEFAULT_INFERENCE_CREDITS_PER_DOLLAR
303
+ if isinstance(value, bool):
304
+ return None
305
+ if isinstance(value, int) and value > 0:
306
+ return value
307
+ if isinstance(value, float) and value > 0:
308
+ return int(value)
309
+ return None
310
+
290
311
  @staticmethod
291
312
  def normalize_platform_model_ids(model_ids: list[str] | None) -> list[str]:
292
313
  if not model_ids:
@@ -355,8 +376,13 @@ class ModelManager:
355
376
  if name:
356
377
  result["name"] = name
357
378
  for extra_field in (
379
+ "order",
358
380
  "cost",
359
381
  "limits",
382
+ "cost_input",
383
+ "cost_output",
384
+ "context_window",
385
+ "max_output",
360
386
  "capabilities",
361
387
  "modalities",
362
388
  "knowledge",
@@ -744,6 +770,9 @@ class ModelManager:
744
770
  self._state.preference_platform_model_ids = self.normalize_platform_model_ids(
745
771
  platform_model_ids
746
772
  )
773
+ self._state.inference_credits_per_dollar = self.parse_inference_credits_per_dollar(
774
+ preferences.get("inference_credits_per_dollar")
775
+ )
747
776
  self._state.access_restricted = bool(preferences.get("access_restricted"))
748
777
  self.apply_restricted_current_model_fallback()
749
778
  if not self._state.platform_models:
@@ -787,7 +816,11 @@ class ModelManager:
787
816
  return None
788
817
  try:
789
818
  t0 = time.monotonic()
790
- result = await asyncio.to_thread(api.provision_inference_key, org)
819
+ result = await asyncio.to_thread(
820
+ api.provision_inference_key,
821
+ org,
822
+ self._tui_client_id,
823
+ )
791
824
  logger.debug(
792
825
  "LiteLLM key provisioned | elapsed={:.0f}ms",
793
826
  (time.monotonic() - t0) * 1000,
@@ -63,6 +63,7 @@ class ModelEntry:
63
63
  knowledge: str | None = None
64
64
  release_date: str | None = None
65
65
  open_weights: bool | None = None
66
+ order: int | None = None
66
67
 
67
68
 
68
69
  @dataclass(slots=True, frozen=True)
@@ -129,9 +130,48 @@ def _format_context(value: int | None) -> str:
129
130
  return _format_compact_int(value)
130
131
 
131
132
 
132
- def _format_price(input_cost: float | None, output_cost: float | None) -> str:
133
+ def _format_compact_number(value: float) -> str:
134
+ rounded_value = round(value, 6)
135
+ if abs(rounded_value) >= 1_000_000:
136
+ return f"{rounded_value / 1_000_000:g}m"
137
+ if abs(rounded_value) >= 1_000:
138
+ return f"{rounded_value / 1_000:g}k"
139
+ if rounded_value.is_integer():
140
+ return str(int(rounded_value))
141
+ return f"{rounded_value:g}"
142
+
143
+
144
+ def _format_price(
145
+ input_cost: float | None,
146
+ output_cost: float | None,
147
+ *,
148
+ source: t.Literal["dreadnode", "byok"],
149
+ inference_credits_per_dollar: float | None,
150
+ ) -> str:
133
151
  if input_cost is None and output_cost is None:
134
152
  return "-"
153
+
154
+ if source == "dreadnode":
155
+ if not (
156
+ isinstance(inference_credits_per_dollar, int | float)
157
+ and inference_credits_per_dollar > 0
158
+ ):
159
+ return "-"
160
+ input_credits = (
161
+ _format_compact_number(input_cost * inference_credits_per_dollar)
162
+ if input_cost is not None
163
+ else None
164
+ )
165
+ output_credits = (
166
+ _format_compact_number(output_cost * inference_credits_per_dollar)
167
+ if output_cost is not None
168
+ else None
169
+ )
170
+ if input_credits is not None and output_credits is not None:
171
+ return f"{input_credits}/{output_credits} cr"
172
+ value = input_credits if input_credits is not None else output_credits
173
+ return f"{value} cr"
174
+
135
175
  if input_cost is not None and output_cost is not None:
136
176
  return f"${input_cost:g}/${output_cost:g}"
137
177
  value = input_cost if input_cost is not None else output_cost
@@ -146,27 +186,57 @@ def _format_open_weights(value: bool | None) -> str:
146
186
  return "-"
147
187
 
148
188
 
189
+ def _parse_float_value(raw: t.Any) -> float | None:
190
+ if isinstance(raw, bool):
191
+ return None
192
+ if isinstance(raw, int | float):
193
+ return float(raw)
194
+ return None
195
+
196
+
197
+ def _parse_int_value(raw: t.Any) -> int | None:
198
+ if isinstance(raw, bool):
199
+ return None
200
+ if isinstance(raw, int | float):
201
+ return int(raw)
202
+ return None
203
+
204
+
149
205
  def _parse_cost_fields(entry: dict[str, t.Any]) -> tuple[float | None, float | None]:
150
206
  cost = entry.get("cost")
151
- if not isinstance(cost, dict):
152
- return (None, None)
153
- input_cost = cost.get("input")
154
- output_cost = cost.get("output")
207
+ input_cost = cost.get("input") if isinstance(cost, dict) else None
208
+ output_cost = cost.get("output") if isinstance(cost, dict) else None
209
+
210
+ parsed_input_cost = _parse_float_value(input_cost)
211
+ if parsed_input_cost is None:
212
+ parsed_input_cost = _parse_float_value(entry.get("cost_input"))
213
+
214
+ parsed_output_cost = _parse_float_value(output_cost)
215
+ if parsed_output_cost is None:
216
+ parsed_output_cost = _parse_float_value(entry.get("cost_output"))
217
+
155
218
  return (
156
- float(input_cost) if isinstance(input_cost, int | float) else None,
157
- float(output_cost) if isinstance(output_cost, int | float) else None,
219
+ parsed_input_cost,
220
+ parsed_output_cost,
158
221
  )
159
222
 
160
223
 
161
224
  def _parse_limit_fields(entry: dict[str, t.Any]) -> tuple[int | None, int | None]:
162
225
  limits = entry.get("limits")
163
- if not isinstance(limits, dict):
164
- return (None, None)
165
- context_window = limits.get("context")
166
- max_output = limits.get("output")
226
+ context_window = limits.get("context") if isinstance(limits, dict) else None
227
+ max_output = limits.get("output") if isinstance(limits, dict) else None
228
+
229
+ parsed_context_window = _parse_int_value(context_window)
230
+ if parsed_context_window is None:
231
+ parsed_context_window = _parse_int_value(entry.get("context_window"))
232
+
233
+ parsed_max_output = _parse_int_value(max_output)
234
+ if parsed_max_output is None:
235
+ parsed_max_output = _parse_int_value(entry.get("max_output"))
236
+
167
237
  return (
168
- int(context_window) if isinstance(context_window, int | float) else None,
169
- int(max_output) if isinstance(max_output, int | float) else None,
238
+ parsed_context_window,
239
+ parsed_max_output,
170
240
  )
171
241
 
172
242
 
@@ -373,6 +443,19 @@ def _build_entries(
373
443
  hosted: dict[str, ModelEntry] = {}
374
444
  byok: dict[str, ModelEntry] = {}
375
445
 
446
+ def parse_order(value: object) -> int | None:
447
+ if isinstance(value, bool):
448
+ return None
449
+ if isinstance(value, int) and value >= 1:
450
+ return value
451
+ if isinstance(value, str) and value.strip():
452
+ try:
453
+ parsed = int(value)
454
+ except ValueError:
455
+ return None
456
+ return parsed if parsed >= 1 else None
457
+ return None
458
+
376
459
  for entry in platform_models:
377
460
  if not isinstance(entry, dict):
378
461
  continue
@@ -411,6 +494,7 @@ def _build_entries(
411
494
  open_weights=entry.get("open_weights")
412
495
  if isinstance(entry.get("open_weights"), bool)
413
496
  else None,
497
+ order=parse_order(entry.get("order")),
414
498
  )
415
499
 
416
500
  for entry in byok_models:
@@ -469,18 +553,19 @@ def _build_entries(
469
553
  source="dreadnode" if current_model.startswith("dn/") else "byok",
470
554
  )
471
555
 
472
- def sort_key(entry: ModelEntry) -> tuple[int, int, str, str]:
473
- return (
474
- 0 if entry.source == "dreadnode" else 1,
475
- 0 if entry.model_id == current_model else 1,
476
- entry.name.lower(),
477
- entry.model_id.lower(),
478
- )
479
-
480
- return sorted([*hosted.values(), *byok.values()], key=sort_key)
556
+ ordered_hosted = sorted(
557
+ enumerate(hosted.values()),
558
+ key=lambda item: (item[1].order is None, item[1].order or 0, item[0]),
559
+ )
560
+ return [*(entry for _index, entry in ordered_hosted), *byok.values()]
481
561
 
482
562
 
483
- def _matches_text(entry: ModelEntry, query: str) -> bool:
563
+ def _matches_text(
564
+ entry: ModelEntry,
565
+ query: str,
566
+ *,
567
+ inference_credits_per_dollar: float | None,
568
+ ) -> bool:
484
569
  if not query:
485
570
  return True
486
571
  haystack = " ".join(
@@ -492,7 +577,12 @@ def _matches_text(entry: ModelEntry, query: str) -> bool:
492
577
  _source_label(entry.source),
493
578
  entry.status or "",
494
579
  _format_context(entry.context_window),
495
- _format_price(entry.cost_input, entry.cost_output),
580
+ _format_price(
581
+ entry.cost_input,
582
+ entry.cost_output,
583
+ source=entry.source,
584
+ inference_credits_per_dollar=inference_credits_per_dollar,
585
+ ),
496
586
  _format_open_weights(entry.open_weights),
497
587
  entry.knowledge or "",
498
588
  entry.release_date or "",
@@ -505,7 +595,12 @@ def _matches_text(entry: ModelEntry, query: str) -> bool:
505
595
  return query.lower() in haystack
506
596
 
507
597
 
508
- def _filter_entries(entries: list[ModelEntry], search: ModelSearch | str) -> list[ModelEntry]:
598
+ def _filter_entries(
599
+ entries: list[ModelEntry],
600
+ search: ModelSearch | str,
601
+ *,
602
+ inference_credits_per_dollar: float | None = None,
603
+ ) -> list[ModelEntry]:
509
604
  """Filter model entries by free text and structured metadata filters."""
510
605
  normalized = _parse_search_query(search) if isinstance(search, str) else search
511
606
 
@@ -534,7 +629,11 @@ def _filter_entries(entries: list[ModelEntry], search: ModelSearch | str) -> lis
534
629
  continue
535
630
  if normalized.max_price is not None and (price is None or price > normalized.max_price):
536
631
  continue
537
- if not _matches_text(entry, normalized.text):
632
+ if not _matches_text(
633
+ entry,
634
+ normalized.text,
635
+ inference_credits_per_dollar=inference_credits_per_dollar,
636
+ ):
538
637
  continue
539
638
  results.append(entry)
540
639
  return results
@@ -563,6 +662,7 @@ class ModelBrowserScreen(Screen[str | None]):
563
662
  platform_models: list[dict[str, t.Any]],
564
663
  byok_models: list[dict[str, t.Any]],
565
664
  current_model: str,
665
+ inference_credits_per_dollar: float | None = None,
566
666
  access_restricted: bool = False,
567
667
  search_models: SearchModelsCallback | None = None,
568
668
  **kwargs: t.Any,
@@ -572,6 +672,7 @@ class ModelBrowserScreen(Screen[str | None]):
572
672
  self._seed_byok_models = list(byok_models)
573
673
  self._catalog_byok_models = list(byok_models)
574
674
  self._current_model = current_model
675
+ self._inference_credits_per_dollar = inference_credits_per_dollar
575
676
  self._access_restricted = access_restricted
576
677
  self._search_models = search_models
577
678
  self._search_loading = False
@@ -631,12 +732,14 @@ class ModelBrowserScreen(Screen[str | None]):
631
732
  platform_models: list[dict[str, t.Any]],
632
733
  byok_models: list[dict[str, t.Any]],
633
734
  current_model: str,
735
+ inference_credits_per_dollar: float | None = None,
634
736
  access_restricted: bool,
635
737
  ) -> None:
636
738
  """Refresh the browser contents from app state."""
637
739
  self._platform_models = list(platform_models)
638
740
  self._seed_byok_models = list(byok_models)
639
741
  self._current_model = current_model
742
+ self._inference_credits_per_dollar = inference_credits_per_dollar
640
743
  self._access_restricted = access_restricted
641
744
  self._rebuild_entries()
642
745
  if not self._search_query:
@@ -842,7 +945,11 @@ class ModelBrowserScreen(Screen[str | None]):
842
945
  self.query_one("#models-header", Static).update(text)
843
946
 
844
947
  def _render_table(self) -> None:
845
- self._visible = _filter_entries(self._entries, _parse_search_query(self._search_query))
948
+ self._visible = _filter_entries(
949
+ self._entries,
950
+ _parse_search_query(self._search_query),
951
+ inference_credits_per_dollar=self._inference_credits_per_dollar,
952
+ )
846
953
  self._cursor = min(self._cursor, max(0, len(self._visible) - 1))
847
954
  self._render_query_bar()
848
955
  table = self.query_one("#models-table", DataTable)
@@ -865,7 +972,12 @@ class ModelBrowserScreen(Screen[str | None]):
865
972
  entry.provider or "-",
866
973
  source,
867
974
  _format_context(entry.context_window),
868
- _format_price(entry.cost_input, entry.cost_output),
975
+ _format_price(
976
+ entry.cost_input,
977
+ entry.cost_output,
978
+ source=entry.source,
979
+ inference_credits_per_dollar=self._inference_credits_per_dollar,
980
+ ),
869
981
  _format_open_weights(entry.open_weights),
870
982
  entry.model_id,
871
983
  key=entry.model_id,
@@ -950,7 +1062,11 @@ class ModelBrowserScreen(Screen[str | None]):
950
1062
  self._catalog_byok_models = list(results)
951
1063
  self._rebuild_entries()
952
1064
  self._cursor = self._current_index(
953
- _filter_entries(self._entries, _parse_search_query(self._search_query))
1065
+ _filter_entries(
1066
+ self._entries,
1067
+ _parse_search_query(self._search_query),
1068
+ inference_credits_per_dollar=self._inference_credits_per_dollar,
1069
+ )
954
1070
  )
955
1071
  if self.is_mounted:
956
1072
  self._render_all()
@@ -5,7 +5,7 @@ SessionContextBar (Zone 1, 2 lines):
5
5
  Line 2: ^A agent ^K model, ^⇧K reasoning
6
6
 
7
7
  PageStatus (Zone 3, 1 line):
8
- 53.4k/200k tok · ⚒ 12 · $0.34 · ? help
8
+ ctx 53.4k/200k tok · ⚒ 12 · usage $0.34 · ? help
9
9
 
10
10
  The token gauge shows ``last_input_tokens / model_max_tokens`` — i.e., the
11
11
  size of the prompt the model just saw against the model's context window.
@@ -18,6 +18,13 @@ The ``⚒`` and ``$X.XX`` segments only render when their values are known
18
18
  and non-zero; on a session with at least one generation that lacked a cost
19
19
  rate the dollar segment is suppressed entirely (matching the backend's
20
20
  null-propagation for ``total_cost_usd``) — partial sums are misleading.
21
+
22
+ The ``ctx`` prefix labels the token gauge as a context-window meter (not a
23
+ quota); the ``usage`` prefix labels the dollar figure as cumulative cost
24
+ for this session only (not balance, not account-wide spend). The dollar
25
+ segment also carries an OSC 8 hyperlink to the public pricing docs so a
26
+ confused user can resolve the unit mismatch with one click in any modern
27
+ terminal — terminals without OSC 8 support simply render plain text.
21
28
  """
22
29
 
23
30
  from __future__ import annotations
@@ -181,6 +188,13 @@ class ContextBar(SessionContextBar):
181
188
 
182
189
  _ISSUE_DISPLAY_SECONDS = 60
183
190
 
191
+ # Public docs page that explains credits, the USD-to-credits rate, what
192
+ # consumes credits, and how the usage-cost figure relates to the org
193
+ # balance. Hard-coded by design: the TUI ships independently of docs and a
194
+ # config lookup would just add a network hop for a value that almost never
195
+ # changes. If this URL moves, the previous one should redirect.
196
+ PRICING_DOCS_URL = "https://docs.dreadnode.io/platform/credits/"
197
+
184
198
 
185
199
  class PageStatus(Static):
186
200
  """Zone 3 — single-line page status below the composer.
@@ -232,6 +246,7 @@ class PageStatus(Static):
232
246
  right = Text(no_wrap=True)
233
247
  if self.last_input_tokens > 0:
234
248
  limit = self.model_max_tokens if self.model_max_tokens > 0 else None
249
+ right.append("ctx ", style=FG_FAINTEST)
235
250
  right.append_text(render_tokens(self.last_input_tokens, limit))
236
251
  right.append(" · ", style=FG_FAINTEST)
237
252
  if self.tool_call_count > 0:
@@ -239,7 +254,11 @@ class PageStatus(Static):
239
254
  right.append(str(self.tool_call_count), style=FG_MUTED)
240
255
  right.append(" · ", style=FG_FAINTEST)
241
256
  if not self.cost_unknown and self.cost_usd > 0:
242
- right.append(_format_cost_usd(self.cost_usd), style=FG_MUTED)
257
+ right.append("usage ", style=FG_FAINTEST)
258
+ right.append(
259
+ _format_cost_usd(self.cost_usd),
260
+ style=f"{FG_MUTED} link {PRICING_DOCS_URL}",
261
+ )
243
262
  right.append(" · ", style=FG_FAINTEST)
244
263
  right.append("? help", style=FG_FAINTEST)
245
264
 
@@ -10,6 +10,7 @@ from rich.text import Text
10
10
 
11
11
  from dreadnode.app.tui.commands import SLASH_COMMANDS
12
12
  from dreadnode.app.tui.theme import ACCENT, BORDER_LIGHT, FG_MUTED, FG_SUBTLE
13
+ from dreadnode.app.tui.widgets.context_bar import PRICING_DOCS_URL
13
14
 
14
15
  _CMD_LOOKUP = {cmd.name: cmd for cmd in SLASH_COMMANDS}
15
16
 
@@ -52,6 +53,16 @@ _SCREENS: list[tuple[str, str]] = [
52
53
  ("F5", "console"),
53
54
  ]
54
55
 
56
+ # Inline explanation of the page-status figures. Phrased so a user reading
57
+ # `?` after seeing `ctx 53.4k/200k tok · ⚒ 12 · usage $0.34` can identify
58
+ # each segment and understand that `usage` cost is in-session-only USD,
59
+ # not balance and not account-wide spend — the unit-mismatch resolution.
60
+ _STATUS_BAR: list[tuple[str, str]] = [
61
+ ("ctx N/M tok", "prompt size relative to the model's context limit"),
62
+ ("⚒ N", "tool calls this session"),
63
+ ("usage $X.XX", "total inference spend this session"),
64
+ ]
65
+
55
66
  _COMMAND_GROUPS: list[tuple[str, list[str]]] = [
56
67
  (
57
68
  "Session",
@@ -105,6 +116,11 @@ def render_help() -> Text:
105
116
  _section(t, "Agent", _AGENT)
106
117
  t.append("\n")
107
118
  _section(t, "Screens", _SCREENS)
119
+ t.append("\n")
120
+ _section(t, "Status", _STATUS_BAR)
121
+ t.append(" Credits and pricing ", style=_DESC)
122
+ t.append(PRICING_DOCS_URL, style=f"{_CMD} link {PRICING_DOCS_URL}")
123
+ t.append("\n")
108
124
 
109
125
  t.append("\n")
110
126
  t.append(" Commands\n", style=f"bold {_HEADING}")
@@ -13,7 +13,7 @@ Dreadnode is a terminal-native platform for offensive security agents. You insta
13
13
 
14
14
  After the [Quickstart](./quickstart.md), you have:
15
15
 
16
- * a logged-in TUI with starter credits attached to your default workspace and project
16
+ * a logged-in TUI with [pre-loaded credits](../platform/credits.md) attached to your default workspace and project
17
17
  * the `web-security` capability installed and runnable against any target you’re authorized to test
18
18
  * a session you can replay end-to-end via `/sessions`
19
19
  * a markdown vulnerability report in `reports/` for any confirmed findings the agent produced
@@ -24,6 +24,7 @@ That’s the first-value path. Everything below extends it.
24
24
 
25
25
  * **[Quickstart](./quickstart.md)** — install, log in, install `web-security`, run your first pentest.
26
26
  * **[Authentication](./authentication.md)** — profiles, workspaces, BYOK provider keys, machine credentials for CI.
27
+ * **[Pricing & credits](../platform/credits.md)** — what credits are, what consumes them, and how to reload before you run your first heavy session.
27
28
  * **[AI Red Teaming](https://docs.dreadnode.io/ai-red-teaming/getting-started/tui/)** — different audience, different flow. If you’re testing model targets, start there.
28
29
  * **[Self-hosting](https://docs.dreadnode.io/self-hosting/)** — deploy the platform on your own Kubernetes cluster.
29
30
 
@@ -127,4 +127,8 @@ The natural fast-follow is **building your own capability** — same shape as `w
127
127
 
128
128
  [Build your own capability](https://docs.dreadnode.io/capabilities/quickstart/)
129
129
 
130
+ Before you go heavy, track what a session costs. Your organization is billed in **credits**, a shared balance that covers inference and sandbox runtime. The `usage $X.XX` figure in the TUI status bar shows your current session’s inference cost in USD. View the Credits page for rates, what consumes credits, and how to reload.
131
+
132
+ [Learn more about credits and pricing](../platform/credits.md)
133
+
130
134
  Looking for something else? Browse the [full capability catalog](../capabilities/installing.md) for network ops, recon, and AI red teaming bundles, or read the [AI Red Teaming guide](https://docs.dreadnode.io/ai-red-teaming/) for model-target work.