dreadnode 2.0.12__tar.gz → 2.0.13__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 (483) hide show
  1. {dreadnode-2.0.12 → dreadnode-2.0.13}/PKG-INFO +1 -1
  2. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/client/interactive.py +0 -4
  3. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/client/managed_client.py +47 -24
  4. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/client/runtime_client.py +10 -4
  5. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/server/app.py +30 -10
  6. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/app.py +18 -9
  7. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/command_dispatcher.py +2 -2
  8. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/profile_manager.py +51 -9
  9. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/sessions_manager.py +9 -3
  10. {dreadnode-2.0.12 → dreadnode-2.0.13}/pyproject.toml +1 -1
  11. {dreadnode-2.0.12 → dreadnode-2.0.13}/.gitignore +0 -0
  12. {dreadnode-2.0.12 → dreadnode-2.0.13}/LICENSE +0 -0
  13. {dreadnode-2.0.12 → dreadnode-2.0.13}/README.md +0 -0
  14. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/__init__.py +0 -0
  15. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/__main__.py +0 -0
  16. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/agents/__init__.py +0 -0
  17. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/agents/agent.py +0 -0
  18. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/agents/events.py +0 -0
  19. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/agents/exceptions.py +0 -0
  20. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/agents/format.py +0 -0
  21. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/agents/hooks.py +0 -0
  22. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/agents/mcp/__init__.py +0 -0
  23. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/agents/mcp/auth.py +0 -0
  24. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/agents/mcp/client.py +0 -0
  25. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/agents/mcp/config.py +0 -0
  26. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/agents/mcp/server.py +0 -0
  27. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/agents/reactions.py +0 -0
  28. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/agents/skills.py +0 -0
  29. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/agents/stopping.py +0 -0
  30. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/agents/subagent.py +0 -0
  31. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/agents/tools.py +0 -0
  32. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/agents/trajectory.py +0 -0
  33. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/__init__.py +0 -0
  34. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/analytics/__init__.py +0 -0
  35. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/analytics/aggregator.py +0 -0
  36. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/analytics/classifier.py +0 -0
  37. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/analytics/compliance.py +0 -0
  38. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/analytics/engine.py +0 -0
  39. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/analytics/recommendations.py +0 -0
  40. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/analytics/types.py +0 -0
  41. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/assessment.py +0 -0
  42. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/autodan_turbo.py +0 -0
  43. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/beast.py +0 -0
  44. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/compliance/__init__.py +0 -0
  45. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/compliance/atlas.py +0 -0
  46. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/compliance/nist.py +0 -0
  47. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/compliance/owasp.py +0 -0
  48. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/compliance/owasp_agentic.py +0 -0
  49. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/compliance/saif.py +0 -0
  50. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/constants.py +0 -0
  51. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/crescendo.py +0 -0
  52. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/data/__init__.py +0 -0
  53. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/data/assets/audio/adversarial_query.mp3 +0 -0
  54. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/data/assets/image/bomb.jpg +0 -0
  55. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/data/assets/image/meth.png +0 -0
  56. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/data/prompts/adversarial_benchmark_subset.csv +0 -0
  57. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/data/prompts/ai_safety.csv +0 -0
  58. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/data/rubrics/data_exfiltration.yaml +0 -0
  59. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/data/rubrics/goal_hijacking.yaml +0 -0
  60. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/data/rubrics/memory_poisoning.yaml +0 -0
  61. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/data/rubrics/privilege_escalation.yaml +0 -0
  62. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/data/rubrics/rce.yaml +0 -0
  63. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/data/rubrics/scope_creep.yaml +0 -0
  64. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/data/rubrics/tool_chaining.yaml +0 -0
  65. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/data/rubrics/tool_selection_safety.yaml +0 -0
  66. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/data/rubrics/unbounded_agency.yaml +0 -0
  67. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/data/rubrics/web_chatbot_security.yaml +0 -0
  68. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/data/templates/crescendo/variant_1.yaml +0 -0
  69. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/data/templates/crescendo/variant_2.yaml +0 -0
  70. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/data/templates/crescendo/variant_3.yaml +0 -0
  71. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/data/templates/crescendo/variant_4.yaml +0 -0
  72. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/data/templates/crescendo/variant_5.yaml +0 -0
  73. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/deep_inception.py +0 -0
  74. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/drattack.py +0 -0
  75. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/events.py +0 -0
  76. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/goat.py +0 -0
  77. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/gptfuzzer.py +0 -0
  78. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/image.py +0 -0
  79. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/multimodal.py +0 -0
  80. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/pair.py +0 -0
  81. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/prompt.py +0 -0
  82. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/rainbow.py +0 -0
  83. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/renellm.py +0 -0
  84. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/reporting/__init__.py +0 -0
  85. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/reporting/json_report.py +0 -0
  86. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/reporting/llm_summary.py +0 -0
  87. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/reporting/markdown.py +0 -0
  88. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/airt/tap.py +0 -0
  89. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/__init__.py +0 -0
  90. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/api/__init__.py +0 -0
  91. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/api/client.py +0 -0
  92. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/api/models.py +0 -0
  93. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/cli/__init__.py +0 -0
  94. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/cli/airt.py +0 -0
  95. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/cli/args.py +0 -0
  96. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/cli/capability.py +0 -0
  97. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/cli/dataset.py +0 -0
  98. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/cli/evaluation.py +0 -0
  99. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/cli/main.py +0 -0
  100. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/cli/model.py +0 -0
  101. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/cli/optimize.py +0 -0
  102. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/cli/runtime.py +0 -0
  103. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/cli/sandbox.py +0 -0
  104. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/cli/shared.py +0 -0
  105. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/cli/task.py +0 -0
  106. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/cli/templates/__init__.py +0 -0
  107. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/cli/templates/init/__init__.py +0 -0
  108. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/cli/templates/init/challenge/Dockerfile +0 -0
  109. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/cli/templates/init/docker-compose.yaml +0 -0
  110. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/cli/templates/init/provision.sh +0 -0
  111. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/cli/templates/init/solution.sh +0 -0
  112. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/cli/templates/init/task-remote.yaml.tmpl +0 -0
  113. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/cli/templates/init/task.yaml.tmpl +0 -0
  114. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/cli/templates/init/teardown.sh +0 -0
  115. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/cli/templates/init/verify.sh +0 -0
  116. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/cli/train.py +0 -0
  117. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/cli/worlds.py +0 -0
  118. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/client/__init__.py +0 -0
  119. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/client/models.py +0 -0
  120. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/client/transports.py +0 -0
  121. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/config.py +0 -0
  122. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/env.py +0 -0
  123. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/main.py +0 -0
  124. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/model_catalog.py +0 -0
  125. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/print_mode.py +0 -0
  126. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/server/__init__.py +0 -0
  127. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/server/auth.py +0 -0
  128. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/server/capability_manager.py +0 -0
  129. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/server/model_resolution.py +0 -0
  130. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/server/prompt.py +0 -0
  131. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/server/prompt_registry.py +0 -0
  132. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/server/runtime_events.py +0 -0
  133. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/server/session_hydrator.py +0 -0
  134. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/server/session_persistence.py +0 -0
  135. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/server/session_policy.py +0 -0
  136. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/server/turn_coordinator.py +0 -0
  137. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/server/utils.py +0 -0
  138. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/server/websocket.py +0 -0
  139. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/server/worker_manager.py +0 -0
  140. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/__init__.py +0 -0
  141. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/auth_flow.py +0 -0
  142. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/capabilities_manager.py +0 -0
  143. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/commands.py +0 -0
  144. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/connection.py +0 -0
  145. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/dreadnode.tcss +0 -0
  146. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/error_handler.py +0 -0
  147. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/model_manager.py +0 -0
  148. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/model_variants.py +0 -0
  149. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/runtime_cache.py +0 -0
  150. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/screen_router.py +0 -0
  151. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/screens/__init__.py +0 -0
  152. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/screens/auth.py +0 -0
  153. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/screens/base.py +0 -0
  154. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/screens/capabilities.py +0 -0
  155. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/screens/capability_docs.py +0 -0
  156. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/screens/connection_error.py +0 -0
  157. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/screens/console.py +0 -0
  158. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/screens/environments.py +0 -0
  159. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/screens/evaluations.py +0 -0
  160. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/screens/model_picker.py +0 -0
  161. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/screens/models.py +0 -0
  162. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/screens/raw_spans.py +0 -0
  163. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/screens/runtimes.py +0 -0
  164. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/screens/sandboxes.py +0 -0
  165. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/screens/secrets.py +0 -0
  166. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/screens/services.py +0 -0
  167. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/screens/sessions.py +0 -0
  168. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/screens/theme_showcase.py +0 -0
  169. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/screens/traces.py +0 -0
  170. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/screens/workspaces.py +0 -0
  171. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/spans_reader.py +0 -0
  172. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/theme.py +0 -0
  173. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/tool_format.py +0 -0
  174. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/turn_coordinator.py +0 -0
  175. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/turn_lifecycle.py +0 -0
  176. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/turn_reducer.py +0 -0
  177. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/turn_state_phase.py +0 -0
  178. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/update_check.py +0 -0
  179. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/widgets/__init__.py +0 -0
  180. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/widgets/agent_dialog.py +0 -0
  181. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/widgets/agent_suggester.py +0 -0
  182. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/widgets/composer.py +0 -0
  183. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/widgets/context_bar.py +0 -0
  184. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/widgets/conversation.py +0 -0
  185. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/widgets/flash.py +0 -0
  186. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/widgets/header_bar.py +0 -0
  187. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/widgets/help_panel.py +0 -0
  188. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/widgets/mention_overlay.py +0 -0
  189. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/widgets/message_queue.py +0 -0
  190. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/widgets/overlay_mixin.py +0 -0
  191. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/widgets/permission_prompt.py +0 -0
  192. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/widgets/profile_dialog.py +0 -0
  193. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/widgets/prompt_info.py +0 -0
  194. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/widgets/session_sidebar.py +0 -0
  195. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/widgets/skills_dialog.py +0 -0
  196. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/widgets/slash_overlay.py +0 -0
  197. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/widgets/status_bar.py +0 -0
  198. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/widgets/throbber.py +0 -0
  199. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/widgets/tool.py +0 -0
  200. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/widgets/tool_progress.py +0 -0
  201. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/widgets/tools_dialog.py +0 -0
  202. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/widgets/welcome.py +0 -0
  203. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/widgets/whoami.py +0 -0
  204. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/app/tui/wire_events.py +0 -0
  205. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/builtin_capabilities/__init__.py +0 -0
  206. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/builtin_capabilities/dreadnode/agents/dreadnode.md +0 -0
  207. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/builtin_capabilities/dreadnode/capability.yaml +0 -0
  208. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/SKILL.md +0 -0
  209. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/capability-components.md +0 -0
  210. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/capability-improvement.md +0 -0
  211. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/runtime-default-capability.md +0 -0
  212. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/SKILL.md +0 -0
  213. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/command-groups.md +0 -0
  214. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/tui-crosswalk.md +0 -0
  215. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-runtime-reference/SKILL.md +0 -0
  216. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/builtin_capabilities/dreadnode/system-prompt.md +0 -0
  217. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/capabilities/__init__.py +0 -0
  218. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/capabilities/capability.py +0 -0
  219. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/capabilities/flags.py +0 -0
  220. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/capabilities/loader.py +0 -0
  221. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/capabilities/sync.py +0 -0
  222. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/capabilities/tool_rules.py +0 -0
  223. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/capabilities/types.py +0 -0
  224. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/capabilities/worker.py +0 -0
  225. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/capabilities/worker_runner.py +0 -0
  226. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/core/__init__.py +0 -0
  227. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/core/conditions.py +0 -0
  228. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/core/discovery.py +0 -0
  229. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/core/environment.py +0 -0
  230. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/core/exceptions.py +0 -0
  231. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/core/execution.py +0 -0
  232. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/core/hook.py +0 -0
  233. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/core/judge.py +0 -0
  234. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/core/load.py +0 -0
  235. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/core/log.py +0 -0
  236. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/core/meta/__init__.py +0 -0
  237. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/core/meta/config.py +0 -0
  238. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/core/meta/context.py +0 -0
  239. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/core/meta/hydrate.py +0 -0
  240. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/core/meta/introspect.py +0 -0
  241. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/core/metric.py +0 -0
  242. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/core/object.py +0 -0
  243. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/core/scorer.py +0 -0
  244. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/core/serialization.py +0 -0
  245. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/core/stopping.py +0 -0
  246. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/core/task.py +0 -0
  247. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/core/transforms.py +0 -0
  248. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/core/types/__init__.py +0 -0
  249. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/core/types/audio.py +0 -0
  250. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/core/types/base.py +0 -0
  251. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/core/types/common.py +0 -0
  252. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/core/types/image.py +0 -0
  253. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/core/types/object_3d.py +0 -0
  254. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/core/types/table.py +0 -0
  255. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/core/types/text.py +0 -0
  256. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/core/types/video.py +0 -0
  257. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/core/util.py +0 -0
  258. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/datasets/__init__.py +0 -0
  259. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/datasets/dataset.py +0 -0
  260. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/datasets/hf.py +0 -0
  261. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/datasets/local.py +0 -0
  262. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/evaluations/__init__.py +0 -0
  263. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/evaluations/console.py +0 -0
  264. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/evaluations/evaluation.py +0 -0
  265. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/evaluations/events.py +0 -0
  266. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/evaluations/format.py +0 -0
  267. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/evaluations/result.py +0 -0
  268. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/evaluations/sample.py +0 -0
  269. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/generators/__init__.py +0 -0
  270. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/generators/caching.py +0 -0
  271. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/generators/chat.py +0 -0
  272. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/generators/data.py +0 -0
  273. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/generators/exceptions.py +0 -0
  274. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/generators/generator/__init__.py +0 -0
  275. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/generators/generator/base.py +0 -0
  276. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/generators/generator/http.py +0 -0
  277. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/generators/generator/litellm_.py +0 -0
  278. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/generators/generator/transformers_.py +0 -0
  279. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/generators/generator/vllm_.py +0 -0
  280. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/generators/message.py +0 -0
  281. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/generators/models.py +0 -0
  282. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/generators/parsing.py +0 -0
  283. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/generators/tokenizer/__init__.py +0 -0
  284. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/generators/tokenizer/base.py +0 -0
  285. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/generators/tokenizer/transformers_.py +0 -0
  286. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/generators/utils.py +0 -0
  287. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/models/__init__.py +0 -0
  288. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/models/hf.py +0 -0
  289. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/models/local.py +0 -0
  290. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/models/model.py +0 -0
  291. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/optimization/__init__.py +0 -0
  292. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/optimization/adapters/__init__.py +0 -0
  293. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/optimization/adapters/agent.py +0 -0
  294. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/optimization/adapters/stack.py +0 -0
  295. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/optimization/api.py +0 -0
  296. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/optimization/backends/__init__.py +0 -0
  297. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/optimization/backends/base.py +0 -0
  298. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/optimization/backends/gepa.py +0 -0
  299. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/optimization/collectors.py +0 -0
  300. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/optimization/config.py +0 -0
  301. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/optimization/console.py +0 -0
  302. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/optimization/events.py +0 -0
  303. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/optimization/format.py +0 -0
  304. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/optimization/jobs.py +0 -0
  305. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/optimization/result.py +0 -0
  306. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/optimization/sampler.py +0 -0
  307. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/optimization/sampling.py +0 -0
  308. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/optimization/search.py +0 -0
  309. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/optimization/stopping.py +0 -0
  310. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/optimization/study.py +0 -0
  311. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/optimization/trial.py +0 -0
  312. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/packaging/__init__.py +0 -0
  313. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/packaging/loader.py +0 -0
  314. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/packaging/manifest.py +0 -0
  315. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/packaging/oci.py +0 -0
  316. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/packaging/package.py +0 -0
  317. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/packaging/task_validation.py +0 -0
  318. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/py.typed +0 -0
  319. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/samplers/__init__.py +0 -0
  320. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/samplers/boundary.py +0 -0
  321. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/samplers/fuzzing.py +0 -0
  322. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/samplers/graph.py +0 -0
  323. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/samplers/grid.py +0 -0
  324. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/samplers/image.py +0 -0
  325. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/samplers/mapelites.py +0 -0
  326. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/samplers/optuna.py +0 -0
  327. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/samplers/random.py +0 -0
  328. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/samplers/registry.py +0 -0
  329. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/samplers/strategy.py +0 -0
  330. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/scorers/__init__.py +0 -0
  331. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/scorers/advanced_jailbreak_detection.py +0 -0
  332. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/scorers/agent_security.py +0 -0
  333. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/scorers/agentic.py +0 -0
  334. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/scorers/agentic_workflow.py +0 -0
  335. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/scorers/classification.py +0 -0
  336. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/scorers/consistency.py +0 -0
  337. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/scorers/contains.py +0 -0
  338. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/scorers/cosine_sim.py +0 -0
  339. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/scorers/credentials.py +0 -0
  340. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/scorers/crucible.py +0 -0
  341. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/scorers/documentation_security.py +0 -0
  342. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/scorers/exfiltration_detection.py +0 -0
  343. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/scorers/format.py +0 -0
  344. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/scorers/harm.py +0 -0
  345. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/scorers/ide_security.py +0 -0
  346. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/scorers/image.py +0 -0
  347. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/scorers/json.py +0 -0
  348. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/scorers/judge.py +0 -0
  349. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/scorers/length.py +0 -0
  350. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/scorers/lexical.py +0 -0
  351. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/scorers/mcp_security.py +0 -0
  352. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/scorers/memorization.py +0 -0
  353. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/scorers/multi_agent_security.py +0 -0
  354. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/scorers/pii.py +0 -0
  355. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/scorers/prompt_leak.py +0 -0
  356. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/scorers/readability.py +0 -0
  357. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/scorers/reasoning_security.py +0 -0
  358. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/scorers/sentiment.py +0 -0
  359. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/scorers/similarity.py +0 -0
  360. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/storage/__init__.py +0 -0
  361. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/storage/providers.py +0 -0
  362. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/storage/session_store.py +0 -0
  363. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/storage/storage.py +0 -0
  364. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/tools/__init__.py +0 -0
  365. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/tools/_ripgrep.py +0 -0
  366. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/tools/apply_patch.py +0 -0
  367. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/tools/dreadnode_cli.py +0 -0
  368. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/tools/editing.py +0 -0
  369. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/tools/execute.py +0 -0
  370. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/tools/fetch.py +0 -0
  371. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/tools/glob.py +0 -0
  372. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/tools/grep.py +0 -0
  373. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/tools/interaction.py +0 -0
  374. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/tools/ls.py +0 -0
  375. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/tools/memory.py +0 -0
  376. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/tools/read.py +0 -0
  377. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/tools/report.py +0 -0
  378. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/tools/task.py +0 -0
  379. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/tools/think.py +0 -0
  380. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/tools/todo.py +0 -0
  381. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/tools/trajectory_search.py +0 -0
  382. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/tools/web_search.py +0 -0
  383. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/tools/write.py +0 -0
  384. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/tracing/__init__.py +0 -0
  385. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/tracing/constants.py +0 -0
  386. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/tracing/convert.py +0 -0
  387. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/tracing/exporter.py +0 -0
  388. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/tracing/exporters.py +0 -0
  389. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/tracing/span.py +0 -0
  390. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/tracing/spans.py +0 -0
  391. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/tracing/trace_converter.py +0 -0
  392. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/__init__.py +0 -0
  393. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/base.py +0 -0
  394. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/dpo.py +0 -0
  395. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/etl/__init__.py +0 -0
  396. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/etl/_common.py +0 -0
  397. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/etl/rl.py +0 -0
  398. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/etl/sft.py +0 -0
  399. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/etl/worlds.py +0 -0
  400. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/events.py +0 -0
  401. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/grpo.py +0 -0
  402. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/jobs.py +0 -0
  403. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/ppo.py +0 -0
  404. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/prime.py +0 -0
  405. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/ray/__init__.py +0 -0
  406. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/ray/async_trainer.py +0 -0
  407. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/ray/config.py +0 -0
  408. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/ray/coordinator.py +0 -0
  409. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/ray/distributed.py +0 -0
  410. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/ray/dpo.py +0 -0
  411. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/ray/experience.py +0 -0
  412. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/ray/fsdp2_learner.py +0 -0
  413. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/ray/inference.py +0 -0
  414. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/ray/learner.py +0 -0
  415. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/ray/multi_turn.py +0 -0
  416. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/ray/ppo.py +0 -0
  417. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/ray/reward_model.py +0 -0
  418. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/ray/rollout_env.py +0 -0
  419. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/ray/rollout_worker.py +0 -0
  420. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/ray/sft.py +0 -0
  421. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/ray/trainer.py +0 -0
  422. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/recipes.py +0 -0
  423. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/rewards/__init__.py +0 -0
  424. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/rewards/aggregator.py +0 -0
  425. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/rewards/functions.py +0 -0
  426. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/rewards/scorer_bridge.py +0 -0
  427. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/rewards/shaping.py +0 -0
  428. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/rewards/types.py +0 -0
  429. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/rollouts/__init__.py +0 -0
  430. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/rollouts/adapters.py +0 -0
  431. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/rollouts/orchestrator.py +0 -0
  432. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/rollouts/types.py +0 -0
  433. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/rollouts/worlds.py +0 -0
  434. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/serving/__init__.py +0 -0
  435. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/serving/vllm_client.py +0 -0
  436. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/sft.py +0 -0
  437. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/tinker/__init__.py +0 -0
  438. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/tinker/config.py +0 -0
  439. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/tinker/data.py +0 -0
  440. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/tinker/renderer.py +0 -0
  441. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/tinker/rl.py +0 -0
  442. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/tinker/trainer.py +0 -0
  443. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/tinker_sft.py +0 -0
  444. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/training/utils.py +0 -0
  445. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/transforms/__init__.py +0 -0
  446. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/transforms/advanced_jailbreak.py +0 -0
  447. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/transforms/adversarial_suffix.py +0 -0
  448. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/transforms/agent_skill.py +0 -0
  449. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/transforms/agentic_workflow.py +0 -0
  450. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/transforms/audio.py +0 -0
  451. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/transforms/browser_agent_attacks.py +0 -0
  452. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/transforms/cipher.py +0 -0
  453. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/transforms/constitutional.py +0 -0
  454. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/transforms/document.py +0 -0
  455. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/transforms/documentation_poison.py +0 -0
  456. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/transforms/encoding.py +0 -0
  457. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/transforms/exfiltration.py +0 -0
  458. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/transforms/flip_attack.py +0 -0
  459. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/transforms/guardrail_bypass.py +0 -0
  460. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/transforms/ide_injection.py +0 -0
  461. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/transforms/image.py +0 -0
  462. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/transforms/injection.py +0 -0
  463. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/transforms/json_tools.py +0 -0
  464. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/transforms/language.py +0 -0
  465. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/transforms/logic_bomb.py +0 -0
  466. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/transforms/mcp_attacks.py +0 -0
  467. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/transforms/multi_agent_attacks.py +0 -0
  468. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/transforms/persuasion.py +0 -0
  469. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/transforms/perturbation.py +0 -0
  470. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/transforms/pii_extraction.py +0 -0
  471. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/transforms/pythonic_tools.py +0 -0
  472. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/transforms/rag_poisoning.py +0 -0
  473. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/transforms/reasoning_attacks.py +0 -0
  474. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/transforms/refine.py +0 -0
  475. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/transforms/response_steering.py +0 -0
  476. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/transforms/stylistic.py +0 -0
  477. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/transforms/substitution.py +0 -0
  478. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/transforms/swap.py +0 -0
  479. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/transforms/system_prompt_extraction.py +0 -0
  480. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/transforms/text.py +0 -0
  481. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/transforms/video.py +0 -0
  482. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/transforms/xml_tools.py +0 -0
  483. {dreadnode-2.0.12 → dreadnode-2.0.13}/dreadnode/version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dreadnode
3
- Version: 2.0.12
3
+ Version: 2.0.13
4
4
  Summary: Dreadnode SDK
5
5
  Project-URL: Homepage, https://dreadnode.io
6
6
  Project-URL: Documentation, https://docs.dreadnode.io
@@ -363,10 +363,6 @@ class _RuntimeInteractiveTransport:
363
363
  http_transport = self._client._http_client._transport
364
364
  if isinstance(http_transport, StreamingASGITransport):
365
365
  return await http_transport.websocket_connect(url=interactive_url, headers=headers)
366
- if self._client._http_client._transport is not None:
367
- raise RuntimeError(
368
- "Interactive websocket transport is unavailable with injected HTTP transport"
369
- )
370
366
 
371
367
  from websockets.asyncio.client import connect
372
368
 
@@ -74,6 +74,13 @@ class ManagedRuntimeClient(RuntimeClient):
74
74
  self._capability_flag_overrides = capability_flag_overrides
75
75
  self._system_prompt_append = system_prompt_append
76
76
  self._lifecycle_ctx: t.Any = None
77
+ # Serialize concurrent start() callers so the slow in-process boot
78
+ # (capability scan + MCP start + litellm warmup) runs once. The
79
+ # event lets passive consumers (e.g. the TUI notify subscriber)
80
+ # wait for the runtime to come up instead of racing start() and
81
+ # kicking off a second boot with empty credentials.
82
+ self._start_lock = asyncio.Lock()
83
+ self._started_event = asyncio.Event()
77
84
 
78
85
  # ── Platform profile ──────────────────────────────────────────
79
86
 
@@ -125,30 +132,46 @@ class ManagedRuntimeClient(RuntimeClient):
125
132
  if self._started:
126
133
  return
127
134
 
128
- if self._in_process:
129
- logger.info("Server start | mode=in-process | url={}", self.server_url)
130
- await self._start_in_process()
131
- self._started = True
132
- return
135
+ async with self._start_lock:
136
+ if self._started:
137
+ return
133
138
 
134
- if await self._is_healthy():
135
- logger.info("Server start | mode=external | url={}", self.server_url)
136
- self._started = True
137
- return
139
+ if self._in_process:
140
+ logger.info("Server start | mode=in-process | url={}", self.server_url)
141
+ await self._start_in_process()
142
+ self._mark_started()
143
+ return
144
+
145
+ if await self._is_healthy():
146
+ logger.info("Server start | mode=external | url={}", self.server_url)
147
+ self._mark_started()
148
+ return
138
149
 
139
- if not self.auto_start:
140
- logger.error("Server unreachable | url={} | auto_start=false", self.server_url)
141
- raise RuntimeError(
142
- "Could not connect to Dreadnode runtime server at "
143
- f"{self.server_url}. The --server flag overrides the local runtime "
144
- "endpoint, not the platform API. Omit --server to auto-start the local "
145
- "runtime, and use /login --server <url> to set the platform API."
146
- )
147
-
148
- logger.info("Server start | mode=spawned | url={}", self.server_url)
149
- self._spawn_local_server()
150
- await self._wait_until_healthy()
150
+ if not self.auto_start:
151
+ logger.error("Server unreachable | url={} | auto_start=false", self.server_url)
152
+ raise RuntimeError(
153
+ "Could not connect to Dreadnode runtime server at "
154
+ f"{self.server_url}. The --server flag overrides the local runtime "
155
+ "endpoint, not the platform API. Omit --server to auto-start the local "
156
+ "runtime, and use /login --server <url> to set the platform API."
157
+ )
158
+
159
+ logger.info("Server start | mode=spawned | url={}", self.server_url)
160
+ self._spawn_local_server()
161
+ await self._wait_until_healthy()
162
+ self._mark_started()
163
+
164
+ async def wait_until_started(self) -> None:
165
+ """Block until ``start()`` has successfully brought the server up."""
166
+ await self._started_event.wait()
167
+
168
+ def _mark_started(self) -> None:
151
169
  self._started = True
170
+ self._started_event.set()
171
+
172
+ def _mark_stopped(self) -> None:
173
+ self._started = False
174
+ self._started_event.clear()
152
175
 
153
176
  async def close(self) -> None:
154
177
  """Close resources and shut down any managed server."""
@@ -215,15 +238,15 @@ class ManagedRuntimeClient(RuntimeClient):
215
238
 
216
239
  reset_app_state()
217
240
 
218
- self._started = False
241
+ self._mark_stopped()
219
242
  await self._start_in_process()
220
- self._started = True
243
+ self._mark_started()
221
244
  return
222
245
 
223
246
  await self.close()
224
247
  self._owned_process = None
225
248
  self._owned_log_file = None
226
- self._started = False
249
+ self._mark_stopped()
227
250
  self._http_client = httpx.AsyncClient(
228
251
  base_url=self.server_url,
229
252
  timeout=None, # noqa: S113 - long-lived local runtime client intentionally disables global timeout
@@ -285,11 +285,17 @@ class RuntimeClient:
285
285
 
286
286
  # ── Session management ────────────────────────────────────────
287
287
 
288
- async def list_sessions(self) -> list[models.SessionInfo]:
289
- """List active sessions from the connected server."""
290
- logger.debug("Listing sessions")
288
+ async def list_sessions(self, *, include_platform: bool = False) -> list[models.SessionInfo]:
289
+ """List active sessions from the connected server.
290
+
291
+ By default only in-process sessions are returned. Pass
292
+ ``include_platform=True`` when the caller needs the full history
293
+ (session picker); it adds a platform API round-trip.
294
+ """
295
+ logger.debug("Listing sessions | include_platform={}", include_platform)
291
296
  await self.start()
292
- response = await self._http_client.get("/api/sessions")
297
+ params = {"include_platform": "true"} if include_platform else None
298
+ response = await self._http_client.get("/api/sessions", params=params)
293
299
  response.raise_for_status()
294
300
  sessions = [models.SessionInfo.from_dict(item) for item in response.json()]
295
301
  logger.debug("Listed sessions | count={}", len(sessions))
@@ -728,21 +728,37 @@ class ServerState:
728
728
  """List all sessions."""
729
729
  return list(self._sessions.values())
730
730
 
731
- def list_session_infos(self) -> list[SessionInfo]:
732
- """List active sessions plus persisted sessions from the API and local store."""
731
+ def list_session_infos(self, *, include_platform: bool = False) -> list[SessionInfo]:
732
+ """List active sessions, optionally merged with platform-persisted sessions.
733
+
734
+ The platform fetch is a ~500ms round-trip that callers only need
735
+ when rendering the full history (session picker, ``/sessions``
736
+ slash command). Boot, runtime swap, and other fast paths skip it
737
+ and get only the in-process set (plus legacy local store).
738
+ """
733
739
  sessions = {session.session_id: session.to_info() for session in self._sessions.values()}
734
740
 
735
- # Try API list first. Scoped to the current user via ``user_id`` so
736
- # the TUI session view doesn't surface other workspace members'
737
- # sessions the platform endpoint defaults to workspace-wide as
738
- # of the workspace-permission-boundary change.
741
+ # Platform-scoped list scoped to the current user via ``user_id``
742
+ # and to this SDK runtime via ``DREADNODE_RUNTIME_ID`` (None on
743
+ # local, the sandbox id on remote). ``save_session`` tags new rows
744
+ # with the same env so the filter stays consistent. Without the
745
+ # runtime scope a local SDK server surfaces sessions from every
746
+ # runtime the user has connected to, and the TUI swap-back lands
747
+ # on a stray remote session. Stop-gap until the platform endpoint
748
+ # gains a first-class runtime_id filter.
749
+ own_runtime_id = os.environ.get("DREADNODE_RUNTIME_ID", "").strip() or None
739
750
  ctx = self._get_api_context()
740
- if ctx is not None:
751
+ if include_platform and ctx is not None:
741
752
  api, org, ws, user_id = ctx
742
753
  try:
743
754
  data = api.list_sessions(org, ws, page_size=100, user_id=user_id)
744
755
  for s in data.get("sessions", []):
745
756
  sid = s.get("id", "")
757
+ session_runtime_id = s.get("runtime_id")
758
+ if session_runtime_id is not None:
759
+ session_runtime_id = str(session_runtime_id)
760
+ if session_runtime_id != own_runtime_id:
761
+ continue
746
762
  if sid and sid not in sessions:
747
763
  sessions[sid] = SessionInfo(
748
764
  session_id=sid,
@@ -2216,9 +2232,13 @@ class SessionRuntime:
2216
2232
 
2217
2233
 
2218
2234
  @app.get("/api/sessions", response_model=list[SessionInfo])
2219
- async def list_sessions() -> list[SessionInfo]:
2220
- """List all active agent sessions."""
2221
- return get_state().list_session_infos()
2235
+ async def list_sessions(include_platform: bool = False) -> list[SessionInfo]:
2236
+ """List active agent sessions.
2237
+
2238
+ Defaults to the in-process set; pass ``include_platform=true`` to
2239
+ merge platform-persisted sessions for this runtime (slower).
2240
+ """
2241
+ return get_state().list_session_infos(include_platform=include_platform)
2222
2242
 
2223
2243
 
2224
2244
  @app.post("/api/sessions", response_model=SessionInfo)
@@ -555,8 +555,8 @@ class _AppProfileRuntime:
555
555
  async def refresh_runtime(self) -> None:
556
556
  await self._app._capabilities_manager.refresh()
557
557
 
558
- async def refresh_server_sessions(self) -> None:
559
- await self._app._refresh_server_sessions()
558
+ async def refresh_server_sessions(self, *, include_platform: bool = False) -> None:
559
+ await self._app._refresh_server_sessions(include_platform=include_platform)
560
560
 
561
561
  async def refresh_skill_names(self) -> None:
562
562
  await self._app._command_dispatcher.refresh_skill_names()
@@ -809,8 +809,8 @@ class _AppSessionsTransport:
809
809
  async def fetch_session_messages(self, session_id: str) -> list[dict[str, t.Any]]:
810
810
  return await self._app.managed_client.fetch_session_messages(session_id)
811
811
 
812
- async def list_sessions(self) -> list[SessionInfo]:
813
- return await self._app.managed_client.list_sessions()
812
+ async def list_sessions(self, *, include_platform: bool = False) -> list[SessionInfo]:
813
+ return await self._app.managed_client.list_sessions(include_platform=include_platform)
814
814
 
815
815
 
816
816
  # ─────────────────────────────────────────────────────────────────────────────
@@ -962,8 +962,8 @@ class _AppCommandActions:
962
962
  ) -> None:
963
963
  self._app._run_command(coro_fn, *args)
964
964
 
965
- async def refresh_server_sessions(self) -> None:
966
- await self._app._refresh_server_sessions()
965
+ async def refresh_server_sessions(self, *, include_platform: bool = False) -> None:
966
+ await self._app._refresh_server_sessions(include_platform=include_platform)
967
967
 
968
968
  async def apply_runtime_info(
969
969
  self,
@@ -2456,8 +2456,8 @@ class DreadnodeTextualApp(App[None]):
2456
2456
  finally:
2457
2457
  self._update_check_done = True
2458
2458
 
2459
- async def _refresh_server_sessions(self) -> None:
2460
- await self._sessions_manager.refresh_from_server()
2459
+ async def _refresh_server_sessions(self, *, include_platform: bool = False) -> None:
2460
+ await self._sessions_manager.refresh_from_server(include_platform=include_platform)
2461
2461
 
2462
2462
  @work(exclusive=True, group="session-picker-refresh")
2463
2463
  async def _refresh_sessions_then_open_picker(self) -> None:
@@ -2466,7 +2466,7 @@ class DreadnodeTextualApp(App[None]):
2466
2466
 
2467
2467
  if self._is_screen_open(SessionPickerScreen):
2468
2468
  return
2469
- await self._sessions_manager.refresh_from_server()
2469
+ await self._sessions_manager.refresh_from_server(include_platform=True)
2470
2470
  self._dismiss_pushed_screens()
2471
2471
  self.push_screen(
2472
2472
  SessionPickerScreen(
@@ -3680,6 +3680,8 @@ class DreadnodeTextualApp(App[None]):
3680
3680
 
3681
3681
  self._update_remote_status()
3682
3682
  self._sync_conversation()
3683
+ if self.active_session_id is not None:
3684
+ self._dismiss_welcome()
3683
3685
 
3684
3686
  async def _on_remote_disconnected(self) -> None:
3685
3687
  """Called after RuntimeConnectionManager.disconnect() succeeds.
@@ -3691,6 +3693,7 @@ class DreadnodeTextualApp(App[None]):
3691
3693
  await self._capabilities_manager.refresh()
3692
3694
  await self._refresh_server_sessions()
3693
3695
  self._update_remote_status()
3696
+ self._sync_conversation()
3694
3697
 
3695
3698
  def _update_remote_status(self) -> None:
3696
3699
  """Update status bar to reflect remote/local connection state."""
@@ -3724,7 +3727,13 @@ class DreadnodeTextualApp(App[None]):
3724
3727
  internally (CAP-WCLI-021); this outer loop only exists to survive
3725
3728
  server-startup races where the first connect attempt fails before
3726
3729
  the local runtime is up.
3730
+
3731
+ Wait for the runtime to be started before calling ``subscribe`` —
3732
+ ``subscribe`` would otherwise call ``start()`` itself and race
3733
+ ``ProfileManager.boot``, booting the in-process server twice
3734
+ (and the first boot with empty platform credentials).
3727
3735
  """
3736
+ await client.wait_until_started()
3728
3737
  backoff = 0.5
3729
3738
  while True:
3730
3739
  try:
@@ -151,7 +151,7 @@ class CommandActions(t.Protocol):
151
151
  """Spawn ``coro_fn(*args)`` as a tracked worker with auth-error recovery."""
152
152
  ...
153
153
 
154
- async def refresh_server_sessions(self) -> None: ...
154
+ async def refresh_server_sessions(self, *, include_platform: bool = False) -> None: ...
155
155
 
156
156
  async def apply_runtime_info(
157
157
  self,
@@ -532,7 +532,7 @@ class CommandDispatcher:
532
532
  # ------------------------------------------------------------------
533
533
 
534
534
  async def list_sessions_command(self) -> None:
535
- await self._actions.refresh_server_sessions()
535
+ await self._actions.refresh_server_sessions(include_platform=True)
536
536
  self._actions.write_session_listing()
537
537
 
538
538
  async def reload_capabilities_command(self) -> None:
@@ -38,6 +38,7 @@ inside a sub-controller.
38
38
  """
39
39
 
40
40
  import asyncio
41
+ import contextlib
41
42
  import time
42
43
  import typing as t
43
44
  from dataclasses import dataclass
@@ -58,6 +59,22 @@ if t.TYPE_CHECKING:
58
59
  from dreadnode.app.tui.update_check import UpdateInfo
59
60
 
60
61
 
62
+ def _log_background_boot_failure(task: "asyncio.Task[t.Any]") -> None:
63
+ """Surface exceptions from a detached runtime-boot task.
64
+
65
+ When early auth failures cause ``boot()`` to return before awaiting
66
+ the runtime-boot task, the task keeps running in the background so
67
+ a subsequent successful auth can reuse it. Without a done-callback,
68
+ any exception raised by the detached task would be lost at GC time
69
+ as ``Task exception was never retrieved``.
70
+ """
71
+ if task.cancelled():
72
+ return
73
+ exc = task.exception()
74
+ if exc is not None:
75
+ logger.opt(exception=exc).debug("Background runtime boot failed")
76
+
77
+
61
78
  # =============================================================================
62
79
  # Shared flow state + ports
63
80
  # =============================================================================
@@ -157,7 +174,7 @@ class ProfileRuntimePort(t.Protocol):
157
174
 
158
175
  async def refresh_runtime(self) -> None: ...
159
176
 
160
- async def refresh_server_sessions(self) -> None: ...
177
+ async def refresh_server_sessions(self, *, include_platform: bool = False) -> None: ...
161
178
 
162
179
  async def refresh_skill_names(self) -> None: ...
163
180
 
@@ -629,6 +646,18 @@ class BootAndAuthRecoveryController:
629
646
 
630
647
  org = profile.organization
631
648
  workspace = profile.workspace
649
+
650
+ # Kick off the local runtime boot now — it only needs the profile's
651
+ # scalar fields (url/api_key/org/workspace/project), which are already
652
+ # in memory. Running it concurrently with the remaining platform API
653
+ # calls (org/workspace validation, identity hydration, user prefs +
654
+ # LiteLLM key provisioning) collapses the critical path substantially.
655
+ self._runtime.set_api_context(api, org, workspace)
656
+ self._runtime.set_platform_profile(profile)
657
+ runtime_start_t0 = time.monotonic()
658
+ runtime_boot_task = asyncio.create_task(self._runtime.start_local_runtime())
659
+ runtime_boot_task.add_done_callback(_log_background_boot_failure)
660
+
632
661
  try:
633
662
  t0 = time.monotonic()
634
663
  await asyncio.to_thread(api.get_organization, org)
@@ -643,6 +672,8 @@ class BootAndAuthRecoveryController:
643
672
  self._invoke_show_auth_modal(
644
673
  reason="Could not verify your account — please sign in again"
645
674
  )
675
+ # Let the runtime boot finish in the background — a subsequent
676
+ # successful auth will restart it with fresh creds anyway.
646
677
  return
647
678
 
648
679
  if not any(getattr(ws, "key", None) == workspace for ws in workspaces):
@@ -664,12 +695,24 @@ class BootAndAuthRecoveryController:
664
695
  logger.opt(exception=True).debug("Boot: identity hydration failed (non-fatal)")
665
696
 
666
697
  resume_session_id = self._state.resume_session_id()
698
+ # Platform models + LiteLLM provisioning can overlap with the tail of
699
+ # the runtime boot and the subsequent runtime refreshes.
700
+ platform_models_t0 = time.monotonic()
701
+ platform_models_task = asyncio.create_task(
702
+ self._models.refresh_platform_models_and_key(api)
703
+ )
667
704
  try:
668
- self._runtime.set_api_context(api, org, workspace)
669
- self._runtime.set_platform_profile(profile)
670
- t0 = time.monotonic()
671
- await self._runtime.start_local_runtime()
672
- logger.debug("Boot timing | runtime_start={:.0f}ms", (time.monotonic() - t0) * 1000)
705
+ try:
706
+ await runtime_boot_task
707
+ except BaseException:
708
+ platform_models_task.cancel()
709
+ with contextlib.suppress(BaseException):
710
+ await platform_models_task
711
+ raise
712
+ logger.debug(
713
+ "Boot timing | runtime_start={:.0f}ms",
714
+ (time.monotonic() - runtime_start_t0) * 1000,
715
+ )
673
716
  t0 = time.monotonic()
674
717
  await self._runtime.refresh_runtime()
675
718
  logger.debug("Boot timing | refresh_runtime={:.0f}ms", (time.monotonic() - t0) * 1000)
@@ -677,11 +720,10 @@ class BootAndAuthRecoveryController:
677
720
  await self._runtime.refresh_server_sessions()
678
721
  logger.debug("Boot timing | refresh_sessions={:.0f}ms", (time.monotonic() - t0) * 1000)
679
722
  try:
680
- t0 = time.monotonic()
681
- await self._models.refresh_platform_models_and_key(api)
723
+ await platform_models_task
682
724
  logger.debug(
683
725
  "Boot timing | platform_models_and_key={:.0f}ms",
684
- (time.monotonic() - t0) * 1000,
726
+ (time.monotonic() - platform_models_t0) * 1000,
685
727
  )
686
728
  except AuthenticationError:
687
729
  self.handle_authentication_error("Session expired — please sign in again")
@@ -453,7 +453,7 @@ class SessionsTransportPort(t.Protocol):
453
453
 
454
454
  async def fetch_session_messages(self, session_id: str) -> list[dict[str, t.Any]]: ...
455
455
 
456
- async def list_sessions(self) -> list[SessionInfo]: ...
456
+ async def list_sessions(self, *, include_platform: bool = False) -> list[SessionInfo]: ...
457
457
 
458
458
 
459
459
  # =============================================================================
@@ -540,7 +540,7 @@ class SessionsManager:
540
540
  # Refresh from server (session list hydration)
541
541
  # ------------------------------------------------------------------
542
542
 
543
- async def refresh_from_server(self) -> None:
543
+ async def refresh_from_server(self, *, include_platform: bool = False) -> None:
544
544
  """Pull the session list from the runtime server and reconcile.
545
545
 
546
546
  Preserves any locally-cached transcript and TUI-only per-session
@@ -550,8 +550,14 @@ class SessionsManager:
550
550
  Promotes the resulting first session to active if the previous
551
551
  ``active_session_id`` no longer exists. Lazy-loads the active
552
552
  session's transcript if the cache is empty.
553
+
554
+ ``include_platform`` is forwarded to the runtime server; set it
555
+ to True only when the caller needs the full persisted history
556
+ (session picker, ``/sessions`` slash command). Fast paths — boot,
557
+ runtime swap, auth refresh — leave it False to avoid a ~500ms
558
+ platform round-trip.
553
559
  """
554
- session_infos = await self._transport.list_sessions()
560
+ session_infos = await self._transport.list_sessions(include_platform=include_platform)
555
561
  logger.debug("Sessions refresh | count={}", len(session_infos))
556
562
  current_model = self._context.current_model()
557
563
  refreshed: dict[str, SessionRecord] = {}
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "dreadnode"
3
- version = "2.0.12"
3
+ version = "2.0.13"
4
4
  description = "Dreadnode SDK"
5
5
  authors = [{ name = "Dreadnode Team", email = "support@dreadnode.io" }]
6
6
  readme = "README.md"
File without changes
File without changes
File without changes