dreadnode 2.0.5__tar.gz → 2.0.6__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.
- {dreadnode-2.0.5 → dreadnode-2.0.6}/PKG-INFO +1 -1
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/agents/agent.py +14 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/agents/events.py +64 -3
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/agents/mcp/client.py +101 -3
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/agents/mcp/config.py +2 -2
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/analytics/types.py +3 -3
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/compliance/atlas.py +2 -2
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/compliance/nist.py +2 -2
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/compliance/owasp.py +2 -2
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/compliance/owasp_agentic.py +2 -2
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/compliance/saif.py +2 -2
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/events.py +3 -3
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/reporting/json_report.py +2 -2
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/reporting/markdown.py +2 -2
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/api/client.py +17 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/api/models.py +6 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/cli/airt.py +2 -1
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/cli/capability.py +23 -15
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/cli/dataset.py +44 -8
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/cli/main.py +6 -5
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/cli/model.py +6 -5
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/cli/shared.py +85 -20
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/cli/task.py +26 -20
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/main.py +2 -2
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/server/app.py +284 -30
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/server/default-agent/tools/coding.py +2 -2
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/app.py +170 -76
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/client.py +45 -8
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/commands.py +40 -7
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/dreadnode.tcss +44 -13
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/event_contract.py +7 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/runtime_cache.py +4 -4
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/screens/__init__.py +4 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/screens/auth.py +3 -3
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/screens/base.py +1 -1
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/screens/capabilities.py +78 -3
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/screens/console.py +2 -2
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/screens/environments.py +1 -1
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/screens/evaluations.py +6 -6
- dreadnode-2.0.6/dreadnode/app/tui/screens/mcp.py +493 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/screens/runtimes.py +8 -8
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/screens/sandboxes.py +5 -5
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/screens/sessions.py +4 -4
- dreadnode-2.0.6/dreadnode/app/tui/screens/theme_showcase.py +446 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/screens/traces.py +1 -1
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/screens/workspaces.py +5 -4
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/theme.py +9 -9
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/turn_reducer.py +9 -4
- dreadnode-2.0.6/dreadnode/app/tui/update_check.py +197 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/widgets/composer.py +0 -2
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/widgets/context_bar.py +44 -3
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/widgets/conversation.py +11 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/widgets/status_bar.py +43 -12
- dreadnode-2.0.6/dreadnode/app/tui/widgets/tool.py +70 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/capabilities/loader.py +3 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/core/metric.py +3 -3
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/core/scorer.py +2 -2
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/core/util.py +1 -1
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/evaluations/events.py +2 -2
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/evaluations/sample.py +2 -2
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/generators/generator/base.py +1 -1
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/generators/generator/litellm_.py +3 -3
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/optimization/events.py +4 -4
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/optimization/trial.py +2 -2
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/packaging/oci.py +1 -1
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/storage/session_store.py +7 -7
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/storage/storage.py +3 -3
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/tools/execute.py +5 -5
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/tools/fetch.py +1 -1
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/tracing/exporters.py +4 -4
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/tracing/span.py +3 -3
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/tracing/trace_converter.py +2 -2
- {dreadnode-2.0.5 → dreadnode-2.0.6}/pyproject.toml +2 -2
- dreadnode-2.0.5/dreadnode/app/tui/update_check.py +0 -105
- dreadnode-2.0.5/dreadnode/app/tui/widgets/mcp_dialog.py +0 -68
- dreadnode-2.0.5/dreadnode/app/tui/widgets/tool.py +0 -60
- {dreadnode-2.0.5 → dreadnode-2.0.6}/.gitignore +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/LICENSE +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/README.md +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/__init__.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/__main__.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/agents/__init__.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/agents/exceptions.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/agents/format.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/agents/hooks.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/agents/mcp/__init__.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/agents/mcp/auth.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/agents/mcp/server.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/agents/reactions.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/agents/skills.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/agents/stopping.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/agents/subagent.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/agents/tools.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/agents/trajectory.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/__init__.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/analytics/__init__.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/analytics/aggregator.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/analytics/classifier.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/analytics/compliance.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/analytics/engine.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/analytics/recommendations.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/assessment.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/autodan_turbo.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/beast.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/compliance/__init__.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/constants.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/crescendo.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/data/__init__.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/data/assets/audio/adversarial_query.mp3 +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/data/assets/image/bomb.jpg +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/data/assets/image/meth.png +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/data/prompts/adversarial_benchmark_subset.csv +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/data/prompts/ai_safety.csv +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/data/rubrics/data_exfiltration.yaml +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/data/rubrics/goal_hijacking.yaml +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/data/rubrics/memory_poisoning.yaml +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/data/rubrics/privilege_escalation.yaml +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/data/rubrics/rce.yaml +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/data/rubrics/scope_creep.yaml +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/data/rubrics/tool_chaining.yaml +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/data/rubrics/tool_selection_safety.yaml +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/data/rubrics/unbounded_agency.yaml +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/data/rubrics/web_chatbot_security.yaml +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/data/templates/crescendo/variant_1.yaml +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/data/templates/crescendo/variant_2.yaml +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/data/templates/crescendo/variant_3.yaml +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/data/templates/crescendo/variant_4.yaml +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/data/templates/crescendo/variant_5.yaml +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/deep_inception.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/drattack.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/goat.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/gptfuzzer.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/image.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/multimodal.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/pair.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/prompt.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/rainbow.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/renellm.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/reporting/__init__.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/reporting/llm_summary.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/airt/tap.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/__init__.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/api/__init__.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/cli/__init__.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/cli/evaluation.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/cli/optimize.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/cli/runtime.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/cli/train.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/cli/worlds.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/print_mode.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/server/__init__.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/server/auth.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/server/default-agent/tools/subagent.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/server/session.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/server/system-prompt.md +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/server/utils.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/__init__.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/connection.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/model_variants.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/screens/model_picker.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/screens/secrets.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/widgets/__init__.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/widgets/agent_dialog.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/widgets/agent_suggester.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/widgets/flash.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/widgets/header_bar.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/widgets/help_panel.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/widgets/mention_overlay.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/widgets/message_queue.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/widgets/overlay_mixin.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/widgets/permission_prompt.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/widgets/prompt_info.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/widgets/session_sidebar.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/widgets/skills_dialog.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/widgets/slash_overlay.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/widgets/throbber.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/widgets/tool_progress.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/widgets/tools_dialog.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/app/tui/widgets/welcome.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/capabilities/__init__.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/capabilities/capability.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/capabilities/sync.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/capabilities/tool_rules.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/capabilities/types.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/core/__init__.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/core/conditions.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/core/discovery.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/core/environment.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/core/exceptions.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/core/execution.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/core/hook.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/core/judge.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/core/load.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/core/log.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/core/meta/__init__.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/core/meta/config.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/core/meta/context.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/core/meta/hydrate.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/core/meta/introspect.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/core/object.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/core/serialization.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/core/stopping.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/core/task.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/core/transforms.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/core/types/__init__.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/core/types/audio.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/core/types/base.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/core/types/common.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/core/types/image.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/core/types/object_3d.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/core/types/table.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/core/types/text.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/core/types/video.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/datasets/__init__.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/datasets/dataset.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/datasets/hf.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/datasets/local.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/evaluations/__init__.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/evaluations/console.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/evaluations/evaluation.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/evaluations/format.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/evaluations/result.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/generators/__init__.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/generators/caching.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/generators/chat.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/generators/data.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/generators/exceptions.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/generators/generator/__init__.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/generators/generator/http.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/generators/generator/transformers_.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/generators/generator/vllm_.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/generators/message.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/generators/models.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/generators/parsing.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/generators/tokenizer/__init__.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/generators/tokenizer/base.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/generators/tokenizer/transformers_.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/generators/utils.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/models/__init__.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/models/hf.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/models/local.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/models/model.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/optimization/__init__.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/optimization/adapters/__init__.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/optimization/adapters/agent.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/optimization/api.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/optimization/backends/__init__.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/optimization/backends/base.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/optimization/backends/gepa.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/optimization/collectors.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/optimization/config.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/optimization/console.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/optimization/format.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/optimization/jobs.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/optimization/result.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/optimization/sampler.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/optimization/sampling.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/optimization/search.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/optimization/stopping.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/optimization/study.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/packaging/__init__.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/packaging/loader.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/packaging/manifest.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/packaging/package.py +1 -1
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/packaging/task_validation.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/py.typed +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/samplers/__init__.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/samplers/boundary.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/samplers/fuzzing.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/samplers/graph.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/samplers/grid.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/samplers/image.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/samplers/mapelites.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/samplers/optuna.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/samplers/random.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/samplers/registry.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/samplers/strategy.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/scorers/__init__.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/scorers/advanced_jailbreak_detection.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/scorers/agent_security.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/scorers/agentic.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/scorers/agentic_workflow.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/scorers/classification.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/scorers/consistency.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/scorers/contains.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/scorers/cosine_sim.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/scorers/credentials.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/scorers/crucible.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/scorers/documentation_security.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/scorers/exfiltration_detection.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/scorers/format.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/scorers/harm.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/scorers/ide_security.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/scorers/image.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/scorers/json.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/scorers/judge.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/scorers/length.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/scorers/lexical.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/scorers/mcp_security.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/scorers/memorization.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/scorers/multi_agent_security.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/scorers/pii.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/scorers/prompt_leak.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/scorers/readability.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/scorers/reasoning_security.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/scorers/sentiment.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/scorers/similarity.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/storage/__init__.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/storage/providers.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/tools/__init__.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/tools/_ripgrep.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/tools/apply_patch.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/tools/editing.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/tools/glob.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/tools/grep.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/tools/interaction.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/tools/ls.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/tools/memory.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/tools/read.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/tools/task.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/tools/think.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/tools/todo.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/tools/web_search.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/tools/write.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/tracing/__init__.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/tracing/constants.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/tracing/convert.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/tracing/exporter.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/tracing/spans.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/__init__.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/base.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/dpo.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/etl/__init__.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/etl/_common.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/etl/rl.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/etl/sft.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/etl/worlds.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/events.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/grpo.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/jobs.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/ppo.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/prime.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/ray/__init__.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/ray/async_trainer.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/ray/config.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/ray/coordinator.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/ray/distributed.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/ray/dpo.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/ray/experience.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/ray/fsdp2_learner.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/ray/inference.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/ray/learner.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/ray/multi_turn.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/ray/ppo.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/ray/reward_model.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/ray/rollout_env.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/ray/rollout_worker.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/ray/sft.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/ray/trainer.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/recipes.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/rewards/__init__.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/rewards/aggregator.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/rewards/functions.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/rewards/scorer_bridge.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/rewards/shaping.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/rewards/types.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/rollouts/__init__.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/rollouts/adapters.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/rollouts/orchestrator.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/rollouts/types.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/rollouts/worlds.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/serving/__init__.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/serving/vllm_client.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/sft.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/tinker/__init__.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/tinker/config.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/tinker/data.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/tinker/renderer.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/tinker/rl.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/tinker/trainer.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/tinker_sft.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/training/utils.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/transforms/__init__.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/transforms/advanced_jailbreak.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/transforms/adversarial_suffix.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/transforms/agent_skill.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/transforms/agentic_workflow.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/transforms/audio.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/transforms/browser_agent_attacks.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/transforms/cipher.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/transforms/constitutional.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/transforms/document.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/transforms/documentation_poison.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/transforms/encoding.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/transforms/exfiltration.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/transforms/flip_attack.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/transforms/guardrail_bypass.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/transforms/ide_injection.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/transforms/image.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/transforms/injection.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/transforms/json_tools.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/transforms/language.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/transforms/logic_bomb.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/transforms/mcp_attacks.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/transforms/multi_agent_attacks.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/transforms/persuasion.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/transforms/perturbation.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/transforms/pii_extraction.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/transforms/pythonic_tools.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/transforms/rag_poisoning.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/transforms/reasoning_attacks.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/transforms/refine.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/transforms/response_steering.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/transforms/stylistic.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/transforms/substitution.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/transforms/swap.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/transforms/system_prompt_extraction.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/transforms/text.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/transforms/video.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/transforms/xml_tools.py +0 -0
- {dreadnode-2.0.5 → dreadnode-2.0.6}/dreadnode/version.py +0 -0
|
@@ -27,6 +27,7 @@ from dreadnode.agents.events import (
|
|
|
27
27
|
AgentStep,
|
|
28
28
|
AgentStopReason,
|
|
29
29
|
CompactionEvent,
|
|
30
|
+
GenerationContent,
|
|
30
31
|
GenerationEnd,
|
|
31
32
|
GenerationError,
|
|
32
33
|
GenerationStart,
|
|
@@ -793,6 +794,19 @@ class Agent(Executor[AgentEvent, Trajectory]):
|
|
|
793
794
|
finally:
|
|
794
795
|
await _event_queue.put(None) # Signal done
|
|
795
796
|
|
|
797
|
+
# Emit generation content BEFORE tools so TUI can
|
|
798
|
+
# render text immediately (ENG-5879)
|
|
799
|
+
last_msg = step_chat.generated[-1] if step_chat.generated else None
|
|
800
|
+
if last_msg and last_msg.content:
|
|
801
|
+
content_event = GenerationContent(
|
|
802
|
+
agent_id=self.agent_id,
|
|
803
|
+
agent_name=self.name,
|
|
804
|
+
step=step_count,
|
|
805
|
+
content=str(last_msg.content)[:4000],
|
|
806
|
+
extra=step_chat.extra,
|
|
807
|
+
)
|
|
808
|
+
yield content_event
|
|
809
|
+
|
|
796
810
|
# Start tools in background
|
|
797
811
|
tools_task = asyncio.create_task(run_all_tools())
|
|
798
812
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import typing as t
|
|
3
|
-
from datetime import
|
|
3
|
+
from datetime import UTC, datetime
|
|
4
4
|
from uuid import UUID, uuid4
|
|
5
5
|
|
|
6
6
|
import typing_extensions as te
|
|
@@ -80,7 +80,7 @@ class AgentEvent(BaseModel):
|
|
|
80
80
|
|
|
81
81
|
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
82
82
|
|
|
83
|
-
timestamp: datetime = Field(default_factory=lambda: datetime.now(
|
|
83
|
+
timestamp: datetime = Field(default_factory=lambda: datetime.now(UTC), kw_only=True)
|
|
84
84
|
agent_id: UUID = Field(default_factory=uuid4)
|
|
85
85
|
agent_name: str | None = None
|
|
86
86
|
status: AgentStatus | None = Field(default=None)
|
|
@@ -775,9 +775,37 @@ class GenerationEnd(AgentStep):
|
|
|
775
775
|
stop_reason: str | None = None
|
|
776
776
|
|
|
777
777
|
def _get_data(self) -> dict[str, t.Any]:
|
|
778
|
+
content = None
|
|
779
|
+
tool_calls = []
|
|
780
|
+
|
|
781
|
+
if self.messages:
|
|
782
|
+
last_msg = self.messages[-1]
|
|
783
|
+
content = str(last_msg.content)[:4000] if last_msg.content else None
|
|
784
|
+
|
|
785
|
+
for tc in last_msg.tool_calls or []:
|
|
786
|
+
try:
|
|
787
|
+
args = json.loads(tc.function.arguments)
|
|
788
|
+
except (json.JSONDecodeError, TypeError):
|
|
789
|
+
args = tc.function.arguments
|
|
790
|
+
tool_calls.append(
|
|
791
|
+
{
|
|
792
|
+
"id": tc.id,
|
|
793
|
+
"name": tc.name,
|
|
794
|
+
"arguments": args,
|
|
795
|
+
}
|
|
796
|
+
)
|
|
797
|
+
|
|
778
798
|
return {
|
|
779
|
-
"model": self.generator.model if self.generator else None,
|
|
780
799
|
"step": self.step,
|
|
800
|
+
"content": content,
|
|
801
|
+
"tool_calls": tool_calls,
|
|
802
|
+
"usage": {
|
|
803
|
+
"input_tokens": self.usage.input_tokens,
|
|
804
|
+
"output_tokens": self.usage.output_tokens,
|
|
805
|
+
"total_tokens": self.usage.total_tokens,
|
|
806
|
+
},
|
|
807
|
+
"stop_reason": self.stop_reason,
|
|
808
|
+
"model": self.generator.model if self.generator else None,
|
|
781
809
|
}
|
|
782
810
|
|
|
783
811
|
def emit(self, span: "TaskSpan") -> None:
|
|
@@ -814,6 +842,38 @@ class GenerationEnd(AgentStep):
|
|
|
814
842
|
super().emit(span)
|
|
815
843
|
|
|
816
844
|
|
|
845
|
+
class GenerationContent(AgentEvent):
|
|
846
|
+
"""Event: The LLM produced content, emitted before tool execution.
|
|
847
|
+
|
|
848
|
+
This is a TUI rendering signal — it carries the generation text so it can
|
|
849
|
+
be displayed immediately, before tools run. GenerationEnd/GenerationStep
|
|
850
|
+
still fire after tools for trajectory, hooks, and telemetry.
|
|
851
|
+
|
|
852
|
+
Attributes:
|
|
853
|
+
step: The step number.
|
|
854
|
+
content: The generated text content.
|
|
855
|
+
tool_calls: Tool calls requested by the generation.
|
|
856
|
+
extra: Additional metadata (reasoning_content, etc.).
|
|
857
|
+
"""
|
|
858
|
+
|
|
859
|
+
step: int = 0
|
|
860
|
+
content: str | None = None
|
|
861
|
+
tool_calls: list[dict[str, t.Any]] = Field(default_factory=list)
|
|
862
|
+
extra: dict[str, t.Any] = Field(default_factory=dict)
|
|
863
|
+
|
|
864
|
+
def _get_data(self) -> dict[str, t.Any]:
|
|
865
|
+
return {
|
|
866
|
+
"step": self.step,
|
|
867
|
+
"content": self.content,
|
|
868
|
+
"tool_calls": self.tool_calls,
|
|
869
|
+
"extra": self.extra,
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
def emit(self, span: "TaskSpan") -> None:
|
|
873
|
+
# No telemetry — GenerationEnd handles that
|
|
874
|
+
pass
|
|
875
|
+
|
|
876
|
+
|
|
817
877
|
class GenerationError(AgentEvent):
|
|
818
878
|
"""Event: An error occurred during a generation step
|
|
819
879
|
|
|
@@ -938,6 +998,7 @@ EVENT_TYPES: dict[str, type[AgentEvent]] = {
|
|
|
938
998
|
"GenerationStart": GenerationStart,
|
|
939
999
|
"GenerationEnd": GenerationEnd,
|
|
940
1000
|
"GenerationStep": GenerationStep,
|
|
1001
|
+
"GenerationContent": GenerationContent,
|
|
941
1002
|
"GenerationError": GenerationError,
|
|
942
1003
|
"ReactStep": ReactStep,
|
|
943
1004
|
"UserInputRequired": UserInputRequired,
|
|
@@ -6,6 +6,7 @@ fallback for streamable-http connections.
|
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
8
|
import asyncio
|
|
9
|
+
import contextlib
|
|
9
10
|
import typing as t
|
|
10
11
|
import warnings
|
|
11
12
|
from contextlib import AsyncExitStack
|
|
@@ -36,6 +37,56 @@ if t.TYPE_CHECKING:
|
|
|
36
37
|
from dreadnode.generators.message import Content
|
|
37
38
|
|
|
38
39
|
|
|
40
|
+
class _StderrCapture:
|
|
41
|
+
"""Async reader that buffers the last N lines from a pipe fd.
|
|
42
|
+
|
|
43
|
+
Used to capture MCP subprocess stderr without blocking and without
|
|
44
|
+
letting it spill into the parent terminal. On connection failure the
|
|
45
|
+
buffered lines are included in the error message so users can see
|
|
46
|
+
why the server process crashed.
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
_MAX_LINES = 50
|
|
50
|
+
|
|
51
|
+
def __init__(self, read_fd: int, exit_stack: AsyncExitStack) -> None:
|
|
52
|
+
import os
|
|
53
|
+
import threading
|
|
54
|
+
|
|
55
|
+
self._lines: list[str] = []
|
|
56
|
+
self._read_file = os.fdopen(read_fd, "r")
|
|
57
|
+
|
|
58
|
+
def _reader() -> None:
|
|
59
|
+
try:
|
|
60
|
+
for raw in self._read_file:
|
|
61
|
+
line = raw.rstrip("\n")
|
|
62
|
+
if line:
|
|
63
|
+
logger.debug("MCP stderr: {}", line)
|
|
64
|
+
self._lines.append(line)
|
|
65
|
+
if len(self._lines) > self._MAX_LINES:
|
|
66
|
+
self._lines.pop(0)
|
|
67
|
+
except (OSError, ValueError):
|
|
68
|
+
pass # fd closed
|
|
69
|
+
|
|
70
|
+
self._thread = threading.Thread(target=_reader, daemon=True)
|
|
71
|
+
self._thread.start()
|
|
72
|
+
exit_stack.callback(self._close)
|
|
73
|
+
|
|
74
|
+
def _close(self) -> None:
|
|
75
|
+
with contextlib.suppress(OSError):
|
|
76
|
+
self._read_file.close()
|
|
77
|
+
self._thread.join(timeout=1)
|
|
78
|
+
|
|
79
|
+
@property
|
|
80
|
+
def output(self) -> str:
|
|
81
|
+
"""Return captured stderr as a single string."""
|
|
82
|
+
return "\n".join(self._lines)
|
|
83
|
+
|
|
84
|
+
@property
|
|
85
|
+
def last_lines(self) -> list[str]:
|
|
86
|
+
"""Return the buffered lines."""
|
|
87
|
+
return list(self._lines)
|
|
88
|
+
|
|
89
|
+
|
|
39
90
|
def _convert_mcp_result_to_message_parts(result: "CallToolResult") -> list[t.Any]:
|
|
40
91
|
from mcp.types import TextResourceContents
|
|
41
92
|
|
|
@@ -121,6 +172,7 @@ class MCPClient:
|
|
|
121
172
|
self._session = None
|
|
122
173
|
self._oauth_config = oauth
|
|
123
174
|
self._init_timeout = init_timeout
|
|
175
|
+
self._stderr_capture: _StderrCapture | None = None
|
|
124
176
|
|
|
125
177
|
@classmethod
|
|
126
178
|
def from_config(cls, config: ServerConfig) -> "MCPClient":
|
|
@@ -185,11 +237,35 @@ class MCPClient:
|
|
|
185
237
|
]
|
|
186
238
|
|
|
187
239
|
async def _connect_via_stdio(self, connection: StdioConnection) -> "ClientSession":
|
|
240
|
+
import os
|
|
241
|
+
|
|
188
242
|
from mcp import ClientSession, StdioServerParameters
|
|
189
243
|
from mcp.client.stdio import stdio_client
|
|
190
244
|
|
|
245
|
+
# Capture subprocess stderr via an OS pipe instead of letting it spill
|
|
246
|
+
# into the parent terminal. An async reader task buffers the last N
|
|
247
|
+
# lines so we can surface them in error messages on connection failure.
|
|
248
|
+
read_fd, write_fd = os.pipe()
|
|
249
|
+
write_file = os.fdopen(write_fd, "w")
|
|
250
|
+
|
|
251
|
+
stderr_capture = _StderrCapture(read_fd, self._exit_stack)
|
|
252
|
+
self._stderr_capture = stderr_capture
|
|
253
|
+
|
|
191
254
|
server_params = StdioServerParameters(**connection)
|
|
192
|
-
|
|
255
|
+
try:
|
|
256
|
+
read, write = await self._exit_stack.enter_async_context(
|
|
257
|
+
stdio_client(server_params, errlog=write_file)
|
|
258
|
+
)
|
|
259
|
+
except BaseException:
|
|
260
|
+
# If the subprocess fails to start (e.g. command not found),
|
|
261
|
+
# close the write end so the reader thread sees EOF and exits.
|
|
262
|
+
write_file.close()
|
|
263
|
+
raise
|
|
264
|
+
# Close parent's write end now that the subprocess has inherited
|
|
265
|
+
# the fd. This ensures the pipe reader sees EOF when the subprocess
|
|
266
|
+
# exits, preventing hangs.
|
|
267
|
+
write_file.close()
|
|
268
|
+
|
|
193
269
|
return await self._exit_stack.enter_async_context(ClientSession(read, write))
|
|
194
270
|
|
|
195
271
|
async def _probe_supports_streamable_http(
|
|
@@ -323,9 +399,27 @@ class MCPClient:
|
|
|
323
399
|
self._status = MCPStatus.CONNECTED
|
|
324
400
|
self._error = None
|
|
325
401
|
|
|
326
|
-
except
|
|
402
|
+
except BaseException as e:
|
|
327
403
|
await self._shutdown()
|
|
328
|
-
|
|
404
|
+
|
|
405
|
+
# anyio TaskGroups wrap failures in BaseExceptionGroup — unwrap
|
|
406
|
+
# to surface the actual root cause (e.g. ConnectionRefusedError)
|
|
407
|
+
# instead of the opaque "unhandled errors in a TaskGroup" message.
|
|
408
|
+
cause = e
|
|
409
|
+
if isinstance(e, BaseExceptionGroup):
|
|
410
|
+
leaf = e.exceptions[0] if e.exceptions else e
|
|
411
|
+
while isinstance(leaf, BaseExceptionGroup) and leaf.exceptions:
|
|
412
|
+
leaf = leaf.exceptions[0]
|
|
413
|
+
cause = leaf
|
|
414
|
+
|
|
415
|
+
error_msg = str(cause)
|
|
416
|
+
|
|
417
|
+
# Append captured subprocess stderr for stdio failures —
|
|
418
|
+
# this surfaces the actual crash output (tracebacks, missing
|
|
419
|
+
# modules, config errors) instead of just "Connection closed".
|
|
420
|
+
if self._stderr_capture and self._stderr_capture.last_lines:
|
|
421
|
+
stderr_tail = "\n".join(self._stderr_capture.last_lines[-10:])
|
|
422
|
+
error_msg = f"{error_msg}\n\nServer stderr:\n{stderr_tail}"
|
|
329
423
|
|
|
330
424
|
# Check for auth-related failures
|
|
331
425
|
error_lower = error_msg.lower()
|
|
@@ -335,6 +429,10 @@ class MCPClient:
|
|
|
335
429
|
self._status = MCPStatus.FAILED
|
|
336
430
|
|
|
337
431
|
self._error = error_msg
|
|
432
|
+
|
|
433
|
+
# Re-raise the unwrapped cause so callers can catch with `except Exception`
|
|
434
|
+
if cause is not e and isinstance(cause, Exception):
|
|
435
|
+
raise cause from e
|
|
338
436
|
raise
|
|
339
437
|
|
|
340
438
|
async def disconnect(self) -> None:
|
|
@@ -8,7 +8,7 @@ StdioServerConfig → stdio, HttpServerConfig → streamable-http.
|
|
|
8
8
|
|
|
9
9
|
import typing as t
|
|
10
10
|
from dataclasses import dataclass, field
|
|
11
|
-
from enum import
|
|
11
|
+
from enum import StrEnum
|
|
12
12
|
from pathlib import Path
|
|
13
13
|
|
|
14
14
|
import typing_extensions as te
|
|
@@ -25,7 +25,7 @@ DEFAULT_SSE_READ_TIMEOUT = 60 * 5
|
|
|
25
25
|
Transport = t.Literal["stdio", "streamable-http"]
|
|
26
26
|
|
|
27
27
|
|
|
28
|
-
class MCPStatus(
|
|
28
|
+
class MCPStatus(StrEnum):
|
|
29
29
|
"""Status of an MCP server connection."""
|
|
30
30
|
|
|
31
31
|
CONNECTED = "connected"
|
|
@@ -8,14 +8,14 @@ from __future__ import annotations
|
|
|
8
8
|
|
|
9
9
|
import typing as t
|
|
10
10
|
from dataclasses import asdict, dataclass, field
|
|
11
|
-
from enum import
|
|
11
|
+
from enum import StrEnum
|
|
12
12
|
|
|
13
13
|
# ---------------------------------------------------------------------------
|
|
14
14
|
# Enums
|
|
15
15
|
# ---------------------------------------------------------------------------
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
class Severity(
|
|
18
|
+
class Severity(StrEnum):
|
|
19
19
|
"""Risk severity levels for attack findings."""
|
|
20
20
|
|
|
21
21
|
CRITICAL = "critical"
|
|
@@ -42,7 +42,7 @@ _SEVERITY_RANK: dict[Severity, int] = {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
|
|
45
|
-
class GoalCategory(
|
|
45
|
+
class GoalCategory(StrEnum):
|
|
46
46
|
"""Impact categories for severity classification.
|
|
47
47
|
|
|
48
48
|
Each category represents a class of attack objective. The category
|
|
@@ -6,10 +6,10 @@ AI/ML-specific attack techniques organized by tactics similar to MITRE ATT&CK.
|
|
|
6
6
|
Reference: https://atlas.mitre.org/
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
|
-
from enum import
|
|
9
|
+
from enum import StrEnum
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
class ATLASTechnique(
|
|
12
|
+
class ATLASTechnique(StrEnum):
|
|
13
13
|
"""
|
|
14
14
|
MITRE ATLAS AI/ML Attack Technique IDs.
|
|
15
15
|
|
|
@@ -6,10 +6,10 @@ Risk management functions and categories for AI systems.
|
|
|
6
6
|
Reference: https://www.nist.gov/itl/ai-risk-management-framework
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
|
-
from enum import
|
|
9
|
+
from enum import StrEnum
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
class NISTAIRMFFunction(
|
|
12
|
+
class NISTAIRMFFunction(StrEnum):
|
|
13
13
|
"""
|
|
14
14
|
NIST AI Risk Management Framework Core Functions.
|
|
15
15
|
|
|
@@ -4,10 +4,10 @@ OWASP Top 10 for LLM Applications 2025.
|
|
|
4
4
|
Reference: https://genai.owasp.org/llm-top-10/
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
from enum import
|
|
7
|
+
from enum import StrEnum
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
class OWASPCategory(
|
|
10
|
+
class OWASPCategory(StrEnum):
|
|
11
11
|
"""
|
|
12
12
|
OWASP Top 10 for LLM Applications 2025.
|
|
13
13
|
|
|
@@ -6,10 +6,10 @@ Security categories for AI/ML systems aligned with Google's security principles.
|
|
|
6
6
|
Reference: https://blog.google/technology/safety-security/google-secure-ai-framework/
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
|
-
from enum import
|
|
9
|
+
from enum import StrEnum
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
class SAIFCategory(
|
|
12
|
+
class SAIFCategory(StrEnum):
|
|
13
13
|
"""
|
|
14
14
|
Google SAIF (Secure AI Framework) Security Categories.
|
|
15
15
|
|
|
@@ -23,7 +23,7 @@ Hierarchy::
|
|
|
23
23
|
from __future__ import annotations
|
|
24
24
|
|
|
25
25
|
import typing as t
|
|
26
|
-
from datetime import
|
|
26
|
+
from datetime import UTC, datetime
|
|
27
27
|
|
|
28
28
|
from pydantic import BaseModel, ConfigDict, Field
|
|
29
29
|
|
|
@@ -77,7 +77,7 @@ class AssessmentEvent(BaseModel):
|
|
|
77
77
|
|
|
78
78
|
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
79
79
|
|
|
80
|
-
timestamp: datetime = Field(default_factory=lambda: datetime.now(
|
|
80
|
+
timestamp: datetime = Field(default_factory=lambda: datetime.now(UTC), kw_only=True)
|
|
81
81
|
assessment_id: str = ""
|
|
82
82
|
assessment_name: str = ""
|
|
83
83
|
|
|
@@ -498,7 +498,7 @@ class TransformApplied(BaseModel):
|
|
|
498
498
|
|
|
499
499
|
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
500
500
|
|
|
501
|
-
timestamp: datetime = Field(default_factory=lambda: datetime.now(
|
|
501
|
+
timestamp: datetime = Field(default_factory=lambda: datetime.now(UTC), kw_only=True)
|
|
502
502
|
transform_name: str = ""
|
|
503
503
|
transform_index: int = 0
|
|
504
504
|
chain_length: int = 0
|
|
@@ -7,7 +7,7 @@ Suitable for CI/CD integration (e.g. ``jq '.summary.severity_breakdown.critical'
|
|
|
7
7
|
from __future__ import annotations
|
|
8
8
|
|
|
9
9
|
import typing as t
|
|
10
|
-
from datetime import
|
|
10
|
+
from datetime import UTC, datetime
|
|
11
11
|
|
|
12
12
|
from dreadnode.airt.analytics.types import (
|
|
13
13
|
ASRBreakdown,
|
|
@@ -87,7 +87,7 @@ def generate_json_report(analytics: CampaignAnalytics) -> dict[str, t.Any]:
|
|
|
87
87
|
|
|
88
88
|
return {
|
|
89
89
|
"meta": {
|
|
90
|
-
"generated_at": datetime.now(tz=
|
|
90
|
+
"generated_at": datetime.now(tz=UTC).isoformat(),
|
|
91
91
|
"report_version": "1.0",
|
|
92
92
|
},
|
|
93
93
|
"summary": {
|
|
@@ -6,7 +6,7 @@ document suitable for human review or conversion to HTML/PDF.
|
|
|
6
6
|
|
|
7
7
|
from __future__ import annotations
|
|
8
8
|
|
|
9
|
-
from datetime import
|
|
9
|
+
from datetime import UTC, datetime
|
|
10
10
|
|
|
11
11
|
from dreadnode.airt.analytics.types import (
|
|
12
12
|
ASRBreakdown,
|
|
@@ -41,7 +41,7 @@ def _truncate(text: str, max_len: int = 500) -> str:
|
|
|
41
41
|
|
|
42
42
|
|
|
43
43
|
def _render_header(analytics: CampaignAnalytics) -> str:
|
|
44
|
-
now = datetime.now(tz=
|
|
44
|
+
now = datetime.now(tz=UTC).strftime("%Y-%m-%d %H:%M:%S UTC")
|
|
45
45
|
stats = analytics.execution_stats
|
|
46
46
|
return (
|
|
47
47
|
"# AIRT Campaign Report\n\n"
|
|
@@ -355,6 +355,18 @@ class ApiClient:
|
|
|
355
355
|
"""DELETE /api/org/{org}/datasets/{name}/{version} - Delete dataset artifact."""
|
|
356
356
|
self.request("DELETE", f"/org/{org}/datasets/{name}/{version}")
|
|
357
357
|
|
|
358
|
+
def download_dataset(
|
|
359
|
+
self, org: str, name: str, version: str, *, format: str = "raw", split: str | None = None
|
|
360
|
+
) -> dict:
|
|
361
|
+
"""POST /api/org/{org}/datasets/{name}/{version}/download - Get presigned download URL."""
|
|
362
|
+
body: dict[str, t.Any] = {"format": format}
|
|
363
|
+
if split:
|
|
364
|
+
body["split"] = split
|
|
365
|
+
response = self.request(
|
|
366
|
+
"POST", f"/org/{org}/datasets/{name}/{version}/download", json_data=body
|
|
367
|
+
)
|
|
368
|
+
return response.json()
|
|
369
|
+
|
|
358
370
|
def list_models(self, org: str) -> list[Package]:
|
|
359
371
|
"""GET /api/org/{org}/models - List models."""
|
|
360
372
|
response = self.request("GET", f"/org/{org}/models")
|
|
@@ -1217,6 +1229,11 @@ class ApiClient:
|
|
|
1217
1229
|
response = self.request("GET", f"/org/{org}/capabilities/{name}/versions")
|
|
1218
1230
|
return t.cast("dict[str, t.Any]", response.json())
|
|
1219
1231
|
|
|
1232
|
+
def list_public_capability_versions(self, owner: str, name: str) -> dict[str, t.Any]:
|
|
1233
|
+
"""GET /capabilities/{owner}/{name}/versions - List public capability versions."""
|
|
1234
|
+
response = self.request("GET", f"/capabilities/{owner}/{name}/versions")
|
|
1235
|
+
return t.cast("dict[str, t.Any]", response.json())
|
|
1236
|
+
|
|
1220
1237
|
def get_capability(self, org: str, name: str, version: str) -> dict[str, t.Any]:
|
|
1221
1238
|
"""GET /org/{org}/capabilities/{name}/{version} - Get artifact detail."""
|
|
1222
1239
|
response = self.request("GET", f"/org/{org}/capabilities/{name}/{version}")
|
|
@@ -857,6 +857,11 @@ class ComponentStatusInfo(BaseModel):
|
|
|
857
857
|
status: t.Literal["ok", "error", "degraded"]
|
|
858
858
|
error: str | None = None
|
|
859
859
|
detail: str | None = None
|
|
860
|
+
# MCP-specific optional fields
|
|
861
|
+
qualified_name: str | None = None
|
|
862
|
+
capability: str | None = None
|
|
863
|
+
transport: str | None = None
|
|
864
|
+
tool_count: int | None = None
|
|
860
865
|
|
|
861
866
|
|
|
862
867
|
class CapabilityInfo(BaseModel):
|
|
@@ -874,6 +879,7 @@ class CapabilityInfo(BaseModel):
|
|
|
874
879
|
origin: dict[str, t.Any] | None = None
|
|
875
880
|
enabled: bool = True
|
|
876
881
|
binding_id: str | None = None
|
|
882
|
+
update_available: str | None = None
|
|
877
883
|
components: list[ComponentStatusInfo] = []
|
|
878
884
|
# Existing fields retained for backward compat
|
|
879
885
|
entry_agent: str | None = None
|
|
@@ -13,6 +13,7 @@ from dreadnode.app.cli.shared import (
|
|
|
13
13
|
_render_airt_assessment_list,
|
|
14
14
|
_render_airt_reports,
|
|
15
15
|
configured_dreadnode,
|
|
16
|
+
console,
|
|
16
17
|
require_workspace_context,
|
|
17
18
|
)
|
|
18
19
|
|
|
@@ -161,7 +162,7 @@ def delete(
|
|
|
161
162
|
dn = configured_dreadnode(platform)
|
|
162
163
|
org, workspace, client = require_workspace_context(dn, label="AIRT")
|
|
163
164
|
client.delete_airt_assessment(org, workspace, assessment_id)
|
|
164
|
-
print(f"Deleted AIRT assessment {assessment_id}")
|
|
165
|
+
console.print(f"Deleted AIRT assessment [dim]{assessment_id}[/dim]")
|
|
165
166
|
|
|
166
167
|
|
|
167
168
|
# ---------------------------------------------------------------------------
|
|
@@ -11,6 +11,7 @@ from dreadnode.app.cli.shared import (
|
|
|
11
11
|
_render_capability_list,
|
|
12
12
|
_sync_progress,
|
|
13
13
|
configured_dreadnode,
|
|
14
|
+
console,
|
|
14
15
|
require_registry_context,
|
|
15
16
|
)
|
|
16
17
|
|
|
@@ -45,13 +46,15 @@ def push(
|
|
|
45
46
|
except (ValueError, RuntimeError) as exc:
|
|
46
47
|
raise SystemExit(str(exc)) from exc
|
|
47
48
|
|
|
49
|
+
name = result.name
|
|
50
|
+
version = result.version
|
|
48
51
|
if result.status == "built":
|
|
49
|
-
print(f"Built {
|
|
52
|
+
console.print(f"Built [cyan]{name}[/cyan]@[dim]{version}[/dim]")
|
|
50
53
|
elif result.status == "up_to_date":
|
|
51
|
-
print(f"{
|
|
54
|
+
console.print(f"[cyan]{name}[/cyan]@[dim]{version}[/dim] already up to date")
|
|
52
55
|
else:
|
|
53
56
|
digest = result.digest or "unknown"
|
|
54
|
-
print(f"Pushed {
|
|
57
|
+
console.print(f"Pushed [cyan]{name}[/cyan]@[dim]{version}[/dim] [dim]({digest})[/dim]")
|
|
55
58
|
|
|
56
59
|
|
|
57
60
|
# ---------------------------------------------------------------------------
|
|
@@ -110,7 +113,7 @@ def delete(
|
|
|
110
113
|
org, client = require_registry_context(dn)
|
|
111
114
|
name, version = _parse_versioned_ref(ref, field_name="ref")
|
|
112
115
|
client.delete_capability(org, name, version)
|
|
113
|
-
print(f"Deleted {org}/{name}@{version}")
|
|
116
|
+
console.print(f"Deleted [dim]{org}/[/dim][cyan]{name}[/cyan]@[dim]{version}[/dim]")
|
|
114
117
|
|
|
115
118
|
|
|
116
119
|
# ---------------------------------------------------------------------------
|
|
@@ -168,10 +171,11 @@ def sync(
|
|
|
168
171
|
)
|
|
169
172
|
|
|
170
173
|
total = len(result.uploaded) + len(result.skipped) + len(result.failed)
|
|
171
|
-
print(
|
|
174
|
+
console.print(
|
|
172
175
|
f"\nSynced {total} capability(ies): "
|
|
173
|
-
f"uploaded={len(result.uploaded)}
|
|
174
|
-
f"
|
|
176
|
+
f"[green]uploaded={len(result.uploaded)}[/green] "
|
|
177
|
+
f"[dim]skipped={len(result.skipped)}[/dim] "
|
|
178
|
+
f"[red]failed={len(result.failed)}[/red]"
|
|
175
179
|
)
|
|
176
180
|
if not result.ok:
|
|
177
181
|
raise SystemExit(1)
|
|
@@ -195,7 +199,7 @@ def validate(
|
|
|
195
199
|
|
|
196
200
|
resolved = Path(path).resolve()
|
|
197
201
|
if not resolved.exists():
|
|
198
|
-
print(f"Path not found: {resolved}")
|
|
202
|
+
console.print(f"[red]Path not found:[/red] {resolved}")
|
|
199
203
|
raise SystemExit(1)
|
|
200
204
|
|
|
201
205
|
# If path contains capability.yaml directly, validate just that one
|
|
@@ -207,7 +211,9 @@ def validate(
|
|
|
207
211
|
d for d in resolved.iterdir() if d.is_dir() and (d / "capability.yaml").exists()
|
|
208
212
|
)
|
|
209
213
|
if not dirs:
|
|
210
|
-
print(
|
|
214
|
+
console.print(
|
|
215
|
+
f"[red]No capability.yaml found in {resolved} or its subdirectories[/red]"
|
|
216
|
+
)
|
|
211
217
|
raise SystemExit(1)
|
|
212
218
|
|
|
213
219
|
errors: list[tuple[str, str]] = []
|
|
@@ -233,20 +239,22 @@ def validate(
|
|
|
233
239
|
|
|
234
240
|
if health_errors:
|
|
235
241
|
warnings.append(cap.name)
|
|
236
|
-
print(f" WARN {cap.name}@{cap.version} ({summary})")
|
|
242
|
+
console.print(f" [yellow]WARN[/yellow] {cap.name}@{cap.version} ({summary})")
|
|
237
243
|
for h in health_errors:
|
|
238
|
-
print(f" {h.get('component', '?')}: {h.get('error', 'unknown')}")
|
|
244
|
+
console.print(f" {h.get('component', '?')}: {h.get('error', 'unknown')}")
|
|
239
245
|
else:
|
|
240
|
-
print(f" OK {cap.name}@{cap.version} ({summary})")
|
|
246
|
+
console.print(f" [green]OK[/green] {cap.name}@{cap.version} ({summary})")
|
|
241
247
|
except (ValueError, FileNotFoundError) as exc:
|
|
242
248
|
errors.append((dir_name, str(exc)))
|
|
243
|
-
print(f" FAIL {dir_name}: {exc}")
|
|
249
|
+
console.print(f" [red]FAIL[/red] {dir_name}: {exc}")
|
|
244
250
|
|
|
245
251
|
total = len(dirs)
|
|
246
252
|
failed = len(errors)
|
|
247
253
|
warned = len(warnings)
|
|
248
|
-
|
|
249
|
-
|
|
254
|
+
ok_count = total - failed - warned
|
|
255
|
+
console.print(
|
|
256
|
+
f"\nValidated {total} capability(ies): "
|
|
257
|
+
f"[green]{ok_count} ok[/green], [yellow]{warned} warn[/yellow], [red]{failed} failed[/red]"
|
|
250
258
|
)
|
|
251
259
|
if errors or (strict and warnings):
|
|
252
260
|
raise SystemExit(1)
|