dreadnode 2.0.32__tar.gz → 2.0.33__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.32 → dreadnode-2.0.33}/PKG-INFO +1 -1
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/__init__.py +10 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/message_parts.py +81 -1
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/multimodal.py +214 -18
- dreadnode-2.0.33/dreadnode/airt/targets/__init__.py +39 -0
- dreadnode-2.0.33/dreadnode/airt/targets/auth.py +74 -0
- dreadnode-2.0.33/dreadnode/airt/targets/factory.py +39 -0
- dreadnode-2.0.33/dreadnode/airt/targets/http.py +45 -0
- dreadnode-2.0.33/dreadnode/airt/targets/message.py +38 -0
- dreadnode-2.0.33/dreadnode/airt/targets/spec.py +57 -0
- dreadnode-2.0.33/dreadnode/airt/targets/streaming/__init__.py +9 -0
- dreadnode-2.0.33/dreadnode/airt/targets/streaming/nova_sonic.py +279 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/model_catalog.py +34 -1
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/server/app.py +18 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/server/websocket.py +7 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/app.py +4 -3
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/model_variants.py +32 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/sessions_manager.py +31 -1
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/widgets/conversation.py +27 -11
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/projects.md +2 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/generators/generator/litellm_.py +82 -4
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/generators/message.py +11 -10
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/scorers/__init__.py +3 -1
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/scorers/judge.py +195 -1
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/tracing/constants.py +6 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/pyproject.toml +1 -1
- {dreadnode-2.0.32 → dreadnode-2.0.33}/.gitignore +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/LICENSE +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/README.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/__main__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/agents/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/agents/agent.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/agents/engines/AGENTS.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/agents/engines/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/agents/engines/base.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/agents/engines/claude_code.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/agents/engines/native.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/agents/events.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/agents/exceptions.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/agents/format.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/agents/hooks.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/agents/judge.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/agents/mcp/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/agents/mcp/auth.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/agents/mcp/client.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/agents/mcp/config.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/agents/mcp/server.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/agents/process_judge.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/agents/reactions.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/agents/skills.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/agents/stopping.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/agents/subagent.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/agents/tool_resolution.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/agents/tools.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/agents/trajectory.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/adversarial_reasoning.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/advpromptier.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/alignment_faking.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/analogy_escalation.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/analytics/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/analytics/aggregator.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/analytics/classifier.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/analytics/compliance.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/analytics/engine.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/analytics/recommendations.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/analytics/types.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/aprt_progressive.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/assessment.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/attention_shifting.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/autodan_turbo.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/autoredteamer.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/beast.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/compliance/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/compliance/atlas.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/compliance/nist.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/compliance/owasp.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/compliance/owasp_agentic.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/compliance/saif.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/constants.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/cot_jailbreak.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/crescendo.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/data/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/data/assets/audio/adversarial_query.mp3 +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/data/assets/image/bomb.jpg +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/data/assets/image/meth.png +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/data/prompts/adversarial_benchmark_subset.csv +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/data/prompts/ai_safety.csv +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/data/rubrics/data_exfiltration.yaml +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/data/rubrics/goal_hijacking.yaml +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/data/rubrics/idor.yaml +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/data/rubrics/memory_poisoning.yaml +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/data/rubrics/privilege_escalation.yaml +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/data/rubrics/rce.yaml +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/data/rubrics/scope_creep.yaml +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/data/rubrics/tool_chaining.yaml +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/data/rubrics/tool_selection_safety.yaml +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/data/rubrics/unbounded_agency.yaml +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/data/rubrics/web_chatbot_security.yaml +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/data/templates/crescendo/variant_1.yaml +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/data/templates/crescendo/variant_2.yaml +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/data/templates/crescendo/variant_3.yaml +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/data/templates/crescendo/variant_4.yaml +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/data/templates/crescendo/variant_5.yaml +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/deep_inception.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/drattack.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/echo_chamber.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/events.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/genetic_persona.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/goat.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/goat_v2.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/gptfuzzer.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/humor_bypass.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/image.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/j2_meta.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/jbdistill.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/jbfuzz.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/lrm_autonomous.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/mapf.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/nexus.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/pair.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/persona_hijack.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/prompt.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/quantization_safety.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/rainbow.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/refusal_aware.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/renellm.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/reporting/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/reporting/json_report.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/reporting/llm_summary.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/reporting/markdown.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/reward_hacking.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/salami_slicing.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/self_persuasion.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/siren.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/tap.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/templatefuzz.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/tmap_trajectory.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/trojail.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/airt/watermark_removal.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/api/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/api/client.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/api/models.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/cli/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/cli/airt.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/cli/args.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/cli/capability.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/cli/dataset.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/cli/environment.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/cli/evaluation.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/cli/inference_model.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/cli/judge.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/cli/main.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/cli/model.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/cli/optimize.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/cli/runtime.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/cli/sandbox.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/cli/secret.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/cli/session.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/cli/shared.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/cli/task.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/cli/task_set.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/cli/templates/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/cli/templates/init/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/cli/templates/init/challenge/Dockerfile +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/cli/templates/init/docker-compose.yaml +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/cli/templates/init/provision.sh +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/cli/templates/init/solution.sh +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/cli/templates/init/task-remote.yaml.tmpl +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/cli/templates/init/task.yaml.tmpl +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/cli/templates/init/teardown.sh +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/cli/templates/init/verify.sh +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/cli/train.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/cli/worlds.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/client/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/client/interactive.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/client/managed_client.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/client/models.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/client/runtime_client.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/client/transports.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/config.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/env.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/main.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/paths.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/print_mode.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/server/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/server/auth.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/server/capability_manager.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/server/model_resolution.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/server/prompt.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/server/prompt_registry.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/server/runtime_events.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/server/session_hydrator.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/server/session_persistence.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/server/turn_coordinator.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/server/utils.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/server/worker_manager.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/server/ws_auth.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/auth_flow.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/capabilities_manager.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/command_dispatcher.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/commands.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/connection.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/dreadnode.tcss +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/error_handler.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/model_manager.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/profile_manager.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/runtime_cache.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/screen_router.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/screens/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/screens/auth.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/screens/base.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/screens/capabilities.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/screens/capability_docs.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/screens/connection_error.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/screens/console.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/screens/environments.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/screens/evaluations.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/screens/models.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/screens/raw_spans.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/screens/readme.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/screens/runtimes.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/screens/sandboxes.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/screens/secrets.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/screens/services.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/screens/sessions.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/screens/theme_showcase.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/screens/traces.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/screens/workspaces.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/spans_reader.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/status_messages.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/theme.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/tool_format.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/turn_coordinator.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/turn_lifecycle.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/turn_reducer.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/turn_state_phase.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/update_check.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/widgets/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/widgets/agent_dialog.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/widgets/agent_suggester.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/widgets/composer.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/widgets/confirm_modal.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/widgets/context_bar.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/widgets/flash.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/widgets/header_bar.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/widgets/help_panel.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/widgets/human_prompt.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/widgets/mention_overlay.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/widgets/message_queue.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/widgets/new_messages_pill.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/widgets/overlay_mixin.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/widgets/permission_prompt.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/widgets/profile_dialog.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/widgets/prompt_info.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/widgets/rewind_picker.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/widgets/session_sidebar.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/widgets/skills_dialog.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/widgets/slash_overlay.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/widgets/status_bar.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/widgets/throbber.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/widgets/tool.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/widgets/tool_progress.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/widgets/tools_dialog.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/widgets/welcome.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/widgets/whoami.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/app/tui/wire_events.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/MAINTAINING.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/agents/dreadnode.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/capability.yaml +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/SKILL.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/capability-improvement.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/methodology-grounding.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/prior-art-audit.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/promoting-capabilities.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/quality-bar.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/INDEX.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/agents.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/custom-engines.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/dependencies-and-checks.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/engines.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/env-vars.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/events.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/flags.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/hooks.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/installing.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/manifest.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/mcp-servers.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/overview.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/policies.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/publishing.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/quickstart.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/skills.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/tools.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/workers-reference.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/workers.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/writing-skills.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/sdk/agents.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/sdk/capabilities.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/tui/default-tools.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references-and-depth.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/runtime-default-capability.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/SKILL.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/INDEX.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/airt.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/capability.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/dataset.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/env.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/evaluation.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/inference-model.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/main.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/model.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/optimize.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/overview.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/runtime.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/sandbox.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/secret.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/task-set.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/task.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/train.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/worlds.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/getting-started/authentication.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/SKILL.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/INDEX.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/capabilities/installing.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/capabilities/overview.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/getting-started/authentication.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/getting-started/overview.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/getting-started/quickstart.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/chat-models.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/credits.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/organizations.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/overview.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/secrets.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/settings.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/users.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/workspaces.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/runtimes/configuration.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/runtimes/managing.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/runtimes/manifest-reference.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/runtimes/overview.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/runtimes/quickstart.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/runtimes/serve.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/sandboxes/environment-lifecycle.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/sandboxes/inspecting.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/sandboxes/overview.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/sandboxes/runtime-limits.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/getting-started/SKILL.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/dreadnode/skills/research-capabilities/SKILL.md +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/self-improvement/.gitignore +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/self-improvement/capability.yaml +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/self-improvement/hooks/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/self-improvement/hooks/observer.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/self-improvement/self_improvement_lib/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/self-improvement/self_improvement_lib/classifier.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/self-improvement/self_improvement_lib/reflector_goal.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/self-improvement/self_improvement_lib/skill_io.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/self-improvement/skills-promoted/.gitkeep +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/self-improvement/skills-proposed/.gitkeep +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/self-improvement/tools/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/self-improvement/tools/reflector.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/builtin_capabilities/self-improvement/tools/skill_stats.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/capabilities/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/capabilities/capability.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/capabilities/flags.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/capabilities/install.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/capabilities/loader.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/capabilities/sync.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/capabilities/tool_rules.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/capabilities/types.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/capabilities/worker.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/capabilities/worker_runner.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/core/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/core/conditions.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/core/discovery.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/core/environment.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/core/exceptions.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/core/execution.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/core/hook.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/core/judge.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/core/load.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/core/log.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/core/meta/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/core/meta/config.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/core/meta/context.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/core/meta/hydrate.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/core/meta/introspect.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/core/metric.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/core/object.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/core/scorer.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/core/serialization.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/core/stopping.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/core/task.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/core/templating.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/core/transforms.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/core/types/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/core/types/audio.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/core/types/base.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/core/types/common.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/core/types/image.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/core/types/object_3d.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/core/types/table.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/core/types/text.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/core/types/video.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/core/util.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/datasets/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/datasets/dataset.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/datasets/hf.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/datasets/local.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/evaluations/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/evaluations/console.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/evaluations/evaluation.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/evaluations/events.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/evaluations/format.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/evaluations/result.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/evaluations/sample.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/generators/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/generators/caching.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/generators/chat.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/generators/data.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/generators/exceptions.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/generators/generator/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/generators/generator/base.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/generators/generator/http.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/generators/generator/transformers_.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/generators/generator/vllm_.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/generators/models.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/generators/parsing.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/generators/proxy.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/generators/tokenizer/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/generators/tokenizer/base.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/generators/tokenizer/transformers_.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/generators/utils.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/items/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/items/config.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/items/models.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/judges/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/judges/outcome.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/judges/trajectory.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/judges/trajectory_tools.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/models/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/models/hf.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/models/local.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/models/model.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/optimization/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/optimization/adapters/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/optimization/adapters/_env_eval.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/optimization/adapters/agent.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/optimization/adapters/env.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/optimization/adapters/runtime.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/optimization/adapters/stack.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/optimization/api.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/optimization/backends/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/optimization/backends/base.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/optimization/backends/gepa.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/optimization/collectors.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/optimization/config.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/optimization/console.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/optimization/events.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/optimization/format.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/optimization/jobs.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/optimization/result.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/optimization/sampler.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/optimization/sampling.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/optimization/search.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/optimization/stopping.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/optimization/study.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/optimization/trial.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/packaging/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/packaging/loader.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/packaging/manifest.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/packaging/oci.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/packaging/package.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/packaging/task_validation.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/policies/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/policies/guard.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/policies/reconciliation.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/policies/rubrics/process/default.yaml +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/py.typed +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/samplers/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/samplers/boundary.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/samplers/fuzzing.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/samplers/graph.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/samplers/grid.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/samplers/image.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/samplers/mapelites.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/samplers/optuna.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/samplers/random.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/samplers/registry.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/samplers/strategy.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/scorers/advanced_jailbreak_detection.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/scorers/agent_security.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/scorers/agentic.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/scorers/agentic_workflow.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/scorers/attack_outcome.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/scorers/classification.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/scorers/consistency.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/scorers/contains.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/scorers/cosine_sim.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/scorers/credentials.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/scorers/crucible.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/scorers/documentation_security.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/scorers/exfiltration_detection.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/scorers/format.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/scorers/harm.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/scorers/ide_security.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/scorers/image.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/scorers/json.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/scorers/judge_ensemble.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/scorers/length.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/scorers/lexical.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/scorers/mcp_security.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/scorers/memorization.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/scorers/multi_agent_security.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/scorers/pii.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/scorers/prompt_leak.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/scorers/readability.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/scorers/reasoning_security.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/scorers/sentiment.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/scorers/similarity.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/scorers/structural_detection.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/scorers/supply_chain_detection.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/storage/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/storage/providers.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/storage/session_store.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/storage/storage.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/tools/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/tools/_ripgrep.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/tools/apply_patch.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/tools/dreadnode_cli.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/tools/editing.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/tools/execute.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/tools/fetch.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/tools/glob.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/tools/grep.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/tools/interaction.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/tools/ls.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/tools/memory.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/tools/project_memory.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/tools/read.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/tools/report.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/tools/report_items.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/tools/task.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/tools/think.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/tools/todo.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/tools/trajectory_search.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/tools/web_extract.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/tools/web_search.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/tools/write.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/tracing/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/tracing/convert.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/tracing/exporter.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/tracing/exporters.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/tracing/span.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/tracing/spans.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/tracing/trace_converter.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/_progress.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/base.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/dpo.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/env_rollouts.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/etl/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/etl/_common.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/etl/rl.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/etl/sft.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/etl/worlds.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/events.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/grpo.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/jobs.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/models.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/ppo.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/prime.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/ray/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/ray/async_trainer.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/ray/config.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/ray/coordinator.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/ray/distributed.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/ray/dpo.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/ray/experience.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/ray/fsdp2_learner.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/ray/inference.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/ray/learner.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/ray/multi_turn.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/ray/ppo.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/ray/reward_model.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/ray/rollout_env.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/ray/rollout_worker.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/ray/sft.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/ray/trainer.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/recipes.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/rewards/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/rewards/aggregator.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/rewards/functions.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/rewards/scorer_bridge.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/rewards/shaping.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/rewards/types.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/rollouts/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/rollouts/adapters.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/rollouts/agent_rollout.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/rollouts/orchestrator.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/rollouts/types.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/rollouts/worlds.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/serving/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/serving/vllm_client.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/sft.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/tinker/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/tinker/config.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/tinker/data.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/tinker/renderer.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/tinker/rl.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/tinker/trainer.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/tinker_sft.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/training/utils.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/transforms/__init__.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/transforms/advanced_jailbreak.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/transforms/adversarial_suffix.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/transforms/agent_skill.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/transforms/agentic_workflow.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/transforms/audio.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/transforms/backdoor_finetune.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/transforms/browser_agent_attacks.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/transforms/cipher.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/transforms/competitive_parity.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/transforms/constitutional.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/transforms/document.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/transforms/documentation_poison.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/transforms/encoding.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/transforms/exfiltration.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/transforms/flip_attack.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/transforms/guardrail_bypass.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/transforms/ide_injection.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/transforms/image.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/transforms/injection.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/transforms/json_tools.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/transforms/language.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/transforms/logic_bomb.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/transforms/mcp_attacks.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/transforms/multi_agent_attacks.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/transforms/multimodal_attacks.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/transforms/persuasion.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/transforms/perturbation.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/transforms/pii_extraction.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/transforms/pythonic_tools.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/transforms/rag_poisoning.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/transforms/reasoning_attacks.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/transforms/refine.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/transforms/response_steering.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/transforms/structural_exploits.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/transforms/stylistic.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/transforms/substitution.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/transforms/supply_chain.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/transforms/swap.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/transforms/system_prompt_extraction.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/transforms/text.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/transforms/video.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/transforms/xml_tools.py +0 -0
- {dreadnode-2.0.32 → dreadnode-2.0.33}/dreadnode/version.py +0 -0
|
@@ -101,6 +101,12 @@ from dreadnode.airt.salami_slicing import salami_slicing_attack
|
|
|
101
101
|
from dreadnode.airt.self_persuasion import self_persuasion_attack
|
|
102
102
|
from dreadnode.airt.siren import siren_attack
|
|
103
103
|
from dreadnode.airt.tap import tap_attack
|
|
104
|
+
from dreadnode.airt.targets import (
|
|
105
|
+
TargetAuth,
|
|
106
|
+
TargetSpec,
|
|
107
|
+
build_target,
|
|
108
|
+
nova_sonic_target,
|
|
109
|
+
)
|
|
104
110
|
from dreadnode.airt.templatefuzz import templatefuzz_attack
|
|
105
111
|
from dreadnode.airt.tmap_trajectory import tmap_trajectory_attack
|
|
106
112
|
from dreadnode.airt.trojail import trojail_attack
|
|
@@ -108,6 +114,8 @@ from dreadnode.airt.watermark_removal import watermark_removal_attack
|
|
|
108
114
|
|
|
109
115
|
__all__ = [
|
|
110
116
|
"Assessment",
|
|
117
|
+
"TargetAuth",
|
|
118
|
+
"TargetSpec",
|
|
111
119
|
"adversarial_reasoning_attack",
|
|
112
120
|
"advpromptier_attack",
|
|
113
121
|
"alignment_faking_attack",
|
|
@@ -117,6 +125,7 @@ __all__ = [
|
|
|
117
125
|
"autodan_turbo_attack",
|
|
118
126
|
"autoredteamer_attack",
|
|
119
127
|
"beast_attack",
|
|
128
|
+
"build_target",
|
|
120
129
|
"cot_jailbreak_attack",
|
|
121
130
|
"crescendo_attack",
|
|
122
131
|
"deep_inception_attack",
|
|
@@ -136,6 +145,7 @@ __all__ = [
|
|
|
136
145
|
"multimodal_attack",
|
|
137
146
|
"nes_attack",
|
|
138
147
|
"nexus_attack",
|
|
148
|
+
"nova_sonic_target",
|
|
139
149
|
"pair_attack",
|
|
140
150
|
"persona_hijack_attack",
|
|
141
151
|
"prompt_attack",
|
|
@@ -46,6 +46,18 @@ def _mime_for_extension(ext: str | None, default: str) -> str:
|
|
|
46
46
|
return _MIME_BY_EXT.get(ext.lower().lstrip("."), default)
|
|
47
47
|
|
|
48
48
|
|
|
49
|
+
# Legacy/alias MIME types that browsers handle poorly, mapped to the standard.
|
|
50
|
+
_MIME_ALIASES = {
|
|
51
|
+
"audio/x-wav": "audio/wav",
|
|
52
|
+
"audio/wave": "audio/wav",
|
|
53
|
+
"audio/x-pn-wav": "audio/wav",
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _normalize_mime(mime: str | None) -> str | None:
|
|
58
|
+
return _MIME_ALIASES.get(mime, mime) if mime else mime
|
|
59
|
+
|
|
60
|
+
|
|
49
61
|
def text_part(
|
|
50
62
|
text: str,
|
|
51
63
|
*,
|
|
@@ -106,9 +118,14 @@ def _media_part(
|
|
|
106
118
|
) -> dict[str, t.Any]:
|
|
107
119
|
"""Build a media message part, storing bytes as a content-addressed artifact."""
|
|
108
120
|
meta = _store_bytes_as_artifact(span, data, filename=filename)
|
|
121
|
+
# Prefer the caller's canonical media_type over log_artifact's guessed MIME:
|
|
122
|
+
# Python's mimetypes maps `.wav` to the legacy `audio/x-wav`, which some
|
|
123
|
+
# browsers refuse to play in an <audio> element. `_normalize_mime` maps such
|
|
124
|
+
# aliases back to the standard type.
|
|
125
|
+
resolved_mime = _normalize_mime(media_type or (meta.get("mime_type") if meta else None))
|
|
109
126
|
source: dict[str, t.Any] = {
|
|
110
127
|
"ref": "artifact",
|
|
111
|
-
"media_type":
|
|
128
|
+
"media_type": resolved_mime,
|
|
112
129
|
"byte_size": (meta.get("size") if meta else None) or len(data),
|
|
113
130
|
"filename": (meta.get("name") if meta else None) or filename,
|
|
114
131
|
}
|
|
@@ -226,12 +243,75 @@ def response_to_parts(
|
|
|
226
243
|
content-addressed artifacts; text is inlined.
|
|
227
244
|
"""
|
|
228
245
|
from dreadnode.core.types import Audio, Image, Video
|
|
246
|
+
from dreadnode.generators.message import (
|
|
247
|
+
ContentAudioInput,
|
|
248
|
+
ContentImageUrl,
|
|
249
|
+
ContentText,
|
|
250
|
+
ContentVideoUrl,
|
|
251
|
+
)
|
|
229
252
|
|
|
230
253
|
parts: list[dict[str, t.Any]] = []
|
|
231
254
|
|
|
232
255
|
def _walk(value: t.Any) -> None:
|
|
233
256
|
if value is None:
|
|
234
257
|
return
|
|
258
|
+
# SDK message content-part types (media-out responses: image/audio/video
|
|
259
|
+
# generated by the target land here). Extract the real bytes/text instead
|
|
260
|
+
# of stringifying the part's repr.
|
|
261
|
+
if isinstance(value, ContentText):
|
|
262
|
+
if value.text:
|
|
263
|
+
parts.append(text_part(value.text))
|
|
264
|
+
return
|
|
265
|
+
if isinstance(value, ContentImageUrl):
|
|
266
|
+
url = value.image_url.url
|
|
267
|
+
mime = "image/png"
|
|
268
|
+
if url.startswith("data:") and ";" in url:
|
|
269
|
+
mime = url[5:].split(";", 1)[0] or mime
|
|
270
|
+
parts.append(
|
|
271
|
+
_media_part(
|
|
272
|
+
span,
|
|
273
|
+
value.to_bytes(),
|
|
274
|
+
kind="image",
|
|
275
|
+
media_type=mime,
|
|
276
|
+
filename="response_image.png",
|
|
277
|
+
transform=None,
|
|
278
|
+
variant="output",
|
|
279
|
+
caption=None,
|
|
280
|
+
)
|
|
281
|
+
)
|
|
282
|
+
return
|
|
283
|
+
if isinstance(value, ContentAudioInput):
|
|
284
|
+
fmt = getattr(value.input_audio, "format", "wav") or "wav"
|
|
285
|
+
parts.append(
|
|
286
|
+
_media_part(
|
|
287
|
+
span,
|
|
288
|
+
value.to_bytes(),
|
|
289
|
+
kind="audio",
|
|
290
|
+
media_type=_mime_for_extension(fmt, "audio/wav"),
|
|
291
|
+
filename=f"response_audio.{fmt}",
|
|
292
|
+
transform=None,
|
|
293
|
+
variant="output",
|
|
294
|
+
caption=None,
|
|
295
|
+
)
|
|
296
|
+
)
|
|
297
|
+
return
|
|
298
|
+
if isinstance(value, ContentVideoUrl):
|
|
299
|
+
import base64 as _b64
|
|
300
|
+
|
|
301
|
+
data = _b64.b64decode(value.file.file_data.split(",", 1)[-1])
|
|
302
|
+
parts.append(
|
|
303
|
+
_media_part(
|
|
304
|
+
span,
|
|
305
|
+
data,
|
|
306
|
+
kind="video",
|
|
307
|
+
media_type=value.file.mimetype or "video/mp4",
|
|
308
|
+
filename=value.file.filename or "response_video.mp4",
|
|
309
|
+
transform=None,
|
|
310
|
+
variant="output",
|
|
311
|
+
caption=None,
|
|
312
|
+
)
|
|
313
|
+
)
|
|
314
|
+
return
|
|
235
315
|
if isinstance(value, str):
|
|
236
316
|
if value:
|
|
237
317
|
parts.append(text_part(value))
|
|
@@ -6,12 +6,14 @@ Probes multimodal models (vision, audio) with transformed inputs.
|
|
|
6
6
|
|
|
7
7
|
from __future__ import annotations
|
|
8
8
|
|
|
9
|
+
import contextlib
|
|
9
10
|
import typing as t
|
|
10
11
|
|
|
11
12
|
from dreadnode.core.transforms import Transform
|
|
12
13
|
from dreadnode.generators.message import (
|
|
13
14
|
ContentAudioInput,
|
|
14
15
|
ContentImageUrl,
|
|
16
|
+
ContentText,
|
|
15
17
|
ContentVideoUrl,
|
|
16
18
|
Message,
|
|
17
19
|
)
|
|
@@ -206,11 +208,122 @@ def _log_multimodal_parts(
|
|
|
206
208
|
logger.debug("Failed to log multimodal message parts", exc_info=True)
|
|
207
209
|
|
|
208
210
|
|
|
211
|
+
def _extract_response_modalities(response: t.Any) -> dict[str, t.Any]:
|
|
212
|
+
"""Decode a target response into per-modality scorable values.
|
|
213
|
+
|
|
214
|
+
Returns a dict keyed by modality (``"text"``/``"image"``/``"audio"``/``"video"``).
|
|
215
|
+
Text is a single concatenated string; media modalities are decoded into native
|
|
216
|
+
SDK media objects (``Image``/``Audio``/``Video``) so a modality-specific scorer
|
|
217
|
+
receives the type it expects. A str response yields ``{"text": <str>}`` — the
|
|
218
|
+
exact value the single-scorer path scored before, keeping text-out behaviour
|
|
219
|
+
(and every other attack that never emits media) unchanged.
|
|
220
|
+
"""
|
|
221
|
+
from dreadnode.core.types import Audio, Image, Video
|
|
222
|
+
|
|
223
|
+
out: dict[str, t.Any] = {}
|
|
224
|
+
texts: list[str] = []
|
|
225
|
+
|
|
226
|
+
def _walk(value: t.Any) -> None:
|
|
227
|
+
if value is None:
|
|
228
|
+
return
|
|
229
|
+
if isinstance(value, str):
|
|
230
|
+
if value:
|
|
231
|
+
texts.append(value)
|
|
232
|
+
elif isinstance(value, ContentText):
|
|
233
|
+
if value.text:
|
|
234
|
+
texts.append(value.text)
|
|
235
|
+
elif isinstance(value, ContentImageUrl):
|
|
236
|
+
with contextlib.suppress(Exception):
|
|
237
|
+
out["image"] = Image(value.to_bytes())
|
|
238
|
+
elif isinstance(value, ContentAudioInput):
|
|
239
|
+
fmt = getattr(value.input_audio, "format", "wav") or "wav"
|
|
240
|
+
with contextlib.suppress(Exception):
|
|
241
|
+
out["audio"] = Audio(value.to_bytes(), format=fmt)
|
|
242
|
+
elif isinstance(value, ContentVideoUrl):
|
|
243
|
+
with contextlib.suppress(Exception):
|
|
244
|
+
import base64
|
|
245
|
+
|
|
246
|
+
data = base64.b64decode(value.file.file_data.split(",", 1)[-1])
|
|
247
|
+
ext = (value.file.mimetype or "video/mp4").split("/")[-1]
|
|
248
|
+
out["video"] = Video(data, format=ext)
|
|
249
|
+
elif isinstance(value, Image):
|
|
250
|
+
out["image"] = value
|
|
251
|
+
elif isinstance(value, Audio):
|
|
252
|
+
out["audio"] = value
|
|
253
|
+
elif isinstance(value, Video):
|
|
254
|
+
out["video"] = value
|
|
255
|
+
elif isinstance(value, (list, tuple)):
|
|
256
|
+
for item in value:
|
|
257
|
+
_walk(item)
|
|
258
|
+
elif isinstance(value, dict):
|
|
259
|
+
for key in ("content", "content_parts", "parts", "text"):
|
|
260
|
+
if key in value:
|
|
261
|
+
_walk(value[key])
|
|
262
|
+
break
|
|
263
|
+
else:
|
|
264
|
+
content = getattr(value, "content_parts", None) or getattr(value, "content", None)
|
|
265
|
+
if content is not None and not isinstance(content, str):
|
|
266
|
+
_walk(content)
|
|
267
|
+
|
|
268
|
+
_walk(response)
|
|
269
|
+
if texts:
|
|
270
|
+
out["text"] = "\n".join(texts)
|
|
271
|
+
return out
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
async def _score_multimodal_response(
|
|
275
|
+
response: t.Any,
|
|
276
|
+
*,
|
|
277
|
+
text_scorer: Scorer[t.Any],
|
|
278
|
+
response_scorers: dict[str, Scorer[t.Any]] | None,
|
|
279
|
+
) -> tuple[float, dict[str, float], str | None]:
|
|
280
|
+
"""Score each response modality and aggregate the trial score by MAX.
|
|
281
|
+
|
|
282
|
+
Red-teaming aggregation is worst-case: if *any* output modality bypasses
|
|
283
|
+
safety, the attack succeeded, so the objective score is the maximum across
|
|
284
|
+
modalities. Per-modality scores are returned for display, and the winning
|
|
285
|
+
(max) modality's rationale is surfaced as the judge reasoning.
|
|
286
|
+
|
|
287
|
+
Backward compatible: with no ``response_scorers`` and a plain text (str)
|
|
288
|
+
response, this scores exactly the same string with ``text_scorer`` as the
|
|
289
|
+
prior single-``scorer.score(response)`` path did — text-out attacks and
|
|
290
|
+
non-multimodal attacks are unaffected. Media modalities with no configured
|
|
291
|
+
scorer are simply skipped (they can't be judged without a media scorer).
|
|
292
|
+
"""
|
|
293
|
+
scorers: dict[str, Scorer[t.Any]] = dict(response_scorers or {})
|
|
294
|
+
scorers.setdefault("text", text_scorer)
|
|
295
|
+
|
|
296
|
+
modalities = _extract_response_modalities(response)
|
|
297
|
+
per_modality: dict[str, float] = {}
|
|
298
|
+
reasons: dict[str, str] = {}
|
|
299
|
+
for modality, value in modalities.items():
|
|
300
|
+
scorer = scorers.get(modality)
|
|
301
|
+
if scorer is None:
|
|
302
|
+
continue
|
|
303
|
+
metric = await scorer.score(value)
|
|
304
|
+
per_modality[modality] = float(metric.value)
|
|
305
|
+
reason = (getattr(metric, "attributes", None) or {}).get("reason")
|
|
306
|
+
if reason:
|
|
307
|
+
reasons[modality] = str(reason)
|
|
308
|
+
|
|
309
|
+
if not per_modality:
|
|
310
|
+
# Nothing decoded (or no applicable scorer) — score the raw response so a
|
|
311
|
+
# degenerate/unknown output shape still yields a metric.
|
|
312
|
+
metric = await text_scorer.score(response)
|
|
313
|
+
reason = (getattr(metric, "attributes", None) or {}).get("reason")
|
|
314
|
+
value = float(metric.value)
|
|
315
|
+
return value, {"text": value}, (str(reason) if reason else None)
|
|
316
|
+
|
|
317
|
+
winning = max(per_modality, key=per_modality.__getitem__)
|
|
318
|
+
return per_modality[winning], per_modality, reasons.get(winning)
|
|
319
|
+
|
|
320
|
+
|
|
209
321
|
def multimodal_attack(
|
|
210
322
|
goal: str,
|
|
211
323
|
target: Task[..., str],
|
|
212
324
|
scorer: Scorer[str],
|
|
213
325
|
*,
|
|
326
|
+
response_scorers: dict[str, Scorer[t.Any]] | None = None,
|
|
214
327
|
image: Image | None = None,
|
|
215
328
|
audio: Audio | None = None,
|
|
216
329
|
video: Video | None = None,
|
|
@@ -235,7 +348,17 @@ def multimodal_attack(
|
|
|
235
348
|
Args:
|
|
236
349
|
goal: The text prompt to send to the model (consistent with goat_attack/tap_attack API).
|
|
237
350
|
target: Task that takes a Message and returns a string response.
|
|
238
|
-
scorer: Scorer to evaluate target
|
|
351
|
+
scorer: Scorer to evaluate the target's *text* response (e.g., jailbreak
|
|
352
|
+
success). Also used as the default text scorer for multimodal output.
|
|
353
|
+
response_scorers: Optional per-modality scorers for multimodal *output*,
|
|
354
|
+
keyed by ``"text"``/``"image"``/``"audio"``/``"video"``. When a target
|
|
355
|
+
emits more than one modality (e.g. text + a generated image), each part
|
|
356
|
+
is scored by its modality's scorer and the trial's objective score is
|
|
357
|
+
the MAX across them — worst-case aggregation, since any single modality
|
|
358
|
+
bypassing safety counts as a successful jailbreak. Per-modality scores
|
|
359
|
+
are recorded on the trial span for display. Media modalities without a
|
|
360
|
+
configured scorer are skipped. Omit this for text-out targets — behaviour
|
|
361
|
+
is then identical to scoring the text response with ``scorer``.
|
|
239
362
|
image: Optional image to include.
|
|
240
363
|
audio: Optional audio to include.
|
|
241
364
|
video: Optional video to include.
|
|
@@ -298,12 +421,70 @@ def multimodal_attack(
|
|
|
298
421
|
applied,
|
|
299
422
|
) = await _apply_transforms(goal, image, audio, video, fitted_transforms)
|
|
300
423
|
|
|
301
|
-
# Build message
|
|
424
|
+
# Build message
|
|
302
425
|
message = _build_message(
|
|
303
426
|
transformed_goal, transformed_image, transformed_audio, transformed_video
|
|
304
427
|
)
|
|
305
|
-
|
|
306
|
-
|
|
428
|
+
|
|
429
|
+
# Record the candidate ("attacker prompt") + trace Input as the transformed
|
|
430
|
+
# goal *text* BEFORE calling the target. If the target then fails (e.g. a
|
|
431
|
+
# provider error, so the response is empty), the finding still shows the
|
|
432
|
+
# real prompt instead of the sampler's {"iteration": N} search state.
|
|
433
|
+
# The Study logs `str(sample.input)` as `transformed_prompt`, so a dict
|
|
434
|
+
# input would render as `{'iteration': 0, 'image': Image(...)}`; the
|
|
435
|
+
# transformed media is carried losslessly in the message parts, so the
|
|
436
|
+
# text is all we log here.
|
|
437
|
+
trial = current_trial.get()
|
|
438
|
+
if trial is not None:
|
|
439
|
+
trial.candidate = transformed_goal
|
|
440
|
+
# The trial span's "candidate" input was logged at TrialStart with the
|
|
441
|
+
# sampler's raw search state; replace it with the goal text.
|
|
442
|
+
from dreadnode.tracing.span import current_task_span as _cts
|
|
443
|
+
|
|
444
|
+
_trial_span = _cts.get()
|
|
445
|
+
if _trial_span is not None:
|
|
446
|
+
with contextlib.suppress(Exception):
|
|
447
|
+
_trial_span._inputs = [
|
|
448
|
+
r for r in _trial_span._inputs if getattr(r, "name", None) != "candidate"
|
|
449
|
+
]
|
|
450
|
+
_trial_span.log_input("candidate", transformed_goal)
|
|
451
|
+
|
|
452
|
+
# Call the target. If it errors (auth failure, unreachable model, rate limit,
|
|
453
|
+
# ...), record the error text as the response so the finding shows *why* it
|
|
454
|
+
# failed instead of an opaque "(no response)", then re-raise so the trial is
|
|
455
|
+
# still classified as an error (not a refusal).
|
|
456
|
+
try:
|
|
457
|
+
span = await target.run(message)
|
|
458
|
+
response = span.output
|
|
459
|
+
except Exception as target_exc:
|
|
460
|
+
error_text = f"[target error] {type(target_exc).__name__}: {str(target_exc)[:500]}"
|
|
461
|
+
with contextlib.suppress(Exception):
|
|
462
|
+
_log_multimodal_parts(
|
|
463
|
+
original_goal=goal,
|
|
464
|
+
transformed_goal=transformed_goal,
|
|
465
|
+
original_image=image,
|
|
466
|
+
transformed_image=transformed_image,
|
|
467
|
+
original_audio=audio,
|
|
468
|
+
transformed_audio=transformed_audio,
|
|
469
|
+
original_video=video,
|
|
470
|
+
transformed_video=transformed_video,
|
|
471
|
+
applied_transforms=applied,
|
|
472
|
+
response=error_text,
|
|
473
|
+
)
|
|
474
|
+
if trial is not None:
|
|
475
|
+
with contextlib.suppress(Exception):
|
|
476
|
+
trial.evaluation_result = EvalResult(
|
|
477
|
+
samples=[Sample(input=transformed_goal, output=error_text, index=iteration)]
|
|
478
|
+
)
|
|
479
|
+
from dreadnode.tracing.span import current_task_span as _err_span_ctx
|
|
480
|
+
|
|
481
|
+
_err_span = _err_span_ctx.get()
|
|
482
|
+
if _err_span is not None:
|
|
483
|
+
from dreadnode.tracing.constants import AIRT_ATTRIBUTE_JUDGE_REASONING
|
|
484
|
+
|
|
485
|
+
with contextlib.suppress(Exception):
|
|
486
|
+
_err_span.set_attribute(AIRT_ATTRIBUTE_JUDGE_REASONING, error_text)
|
|
487
|
+
raise
|
|
307
488
|
|
|
308
489
|
# Persist the multimodal message parts (input + output) as content-addressed
|
|
309
490
|
# artifacts on the trial span, so findings can render each part in the UI.
|
|
@@ -320,18 +501,7 @@ def multimodal_attack(
|
|
|
320
501
|
response=response,
|
|
321
502
|
)
|
|
322
503
|
|
|
323
|
-
# Store sample in trial for tracking (include multimodal content for display)
|
|
324
|
-
trial = current_trial.get()
|
|
325
504
|
if trial is not None:
|
|
326
|
-
# The candidate ("attacker prompt") AND the transformed prompt are the
|
|
327
|
-
# transformed goal *text* — not the sampler's {"iteration": n} params
|
|
328
|
-
# or a dict carrying the raw Image object. The Study logs
|
|
329
|
-
# `str(sample.input)` as `transformed_prompt`, so a dict input would
|
|
330
|
-
# render as `{'iteration': 0, 'image': Image(256x768x3 ...)}` in the
|
|
331
|
-
# UI. The transformed media is carried losslessly in the message
|
|
332
|
-
# parts (see `_log_multimodal_parts`), so the text is all we log here.
|
|
333
|
-
trial.candidate = transformed_goal
|
|
334
|
-
|
|
335
505
|
sample = Sample(
|
|
336
506
|
input=transformed_goal,
|
|
337
507
|
output=response,
|
|
@@ -339,9 +509,35 @@ def multimodal_attack(
|
|
|
339
509
|
)
|
|
340
510
|
trial.evaluation_result = EvalResult(samples=[sample])
|
|
341
511
|
|
|
342
|
-
# Score the response
|
|
343
|
-
|
|
344
|
-
|
|
512
|
+
# Score the response. For multimodal *output* (e.g. text + a generated
|
|
513
|
+
# image), each modality is scored by its own scorer and the objective is
|
|
514
|
+
# the MAX — any modality bypassing safety = a successful jailbreak. For a
|
|
515
|
+
# plain text response this reduces to scoring the text with `scorer`, so
|
|
516
|
+
# text-out attacks are unaffected. The winning modality's rationale is
|
|
517
|
+
# persisted so findings show *why* it scored ("Judge Reasoning"); the
|
|
518
|
+
# per-modality breakdown is recorded for display.
|
|
519
|
+
agg_score, modality_scores, reason = await _score_multimodal_response(
|
|
520
|
+
response, text_scorer=scorer, response_scorers=response_scorers
|
|
521
|
+
)
|
|
522
|
+
from dreadnode.tracing.span import current_task_span
|
|
523
|
+
|
|
524
|
+
trial_span = current_task_span.get()
|
|
525
|
+
if trial_span is not None:
|
|
526
|
+
if reason:
|
|
527
|
+
from dreadnode.tracing.constants import AIRT_ATTRIBUTE_JUDGE_REASONING
|
|
528
|
+
|
|
529
|
+
with contextlib.suppress(Exception):
|
|
530
|
+
trial_span.set_attribute(AIRT_ATTRIBUTE_JUDGE_REASONING, str(reason))
|
|
531
|
+
if len(modality_scores) > 1:
|
|
532
|
+
import json
|
|
533
|
+
|
|
534
|
+
from dreadnode.tracing.constants import AIRT_ATTRIBUTE_MODALITY_SCORES
|
|
535
|
+
|
|
536
|
+
with contextlib.suppress(Exception):
|
|
537
|
+
trial_span.set_attribute(
|
|
538
|
+
AIRT_ATTRIBUTE_MODALITY_SCORES, json.dumps(modality_scores)
|
|
539
|
+
)
|
|
540
|
+
return {OBJECTIVE_SCORE_KEY: agg_score}
|
|
345
541
|
|
|
346
542
|
attack: Study[dict[str, t.Any]] = Study(
|
|
347
543
|
name=name,
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""Universal custom targets for AI red teaming.
|
|
2
|
+
|
|
3
|
+
A red-teaming *target* is any system you can send a message to and read a response
|
|
4
|
+
from. This package turns a declarative :class:`TargetSpec` into a dreadnode ``@task``
|
|
5
|
+
target that plugs straight into ``multimodal_attack`` / the attack studies —
|
|
6
|
+
regardless of where the model is deployed (AWS, Azure ML/AI Foundry, Google Vertex,
|
|
7
|
+
a self-hosted endpoint) or how it authenticates.
|
|
8
|
+
|
|
9
|
+
Two transports:
|
|
10
|
+
|
|
11
|
+
- ``http`` — request/response endpoints. Fully declarative: an endpoint, an auth scheme
|
|
12
|
+
(:class:`TargetAuth`), a JSON request template placing ``{prompt}`` / ``{image_b64}`` /
|
|
13
|
+
``{audio_b64}`` / ``{video_b64}``, and a JSONPath to the response text. Covers Azure
|
|
14
|
+
ML / AI Foundry, Vertex ``predict``, SageMaker sync-invoke, OpenAI-compatible, etc.
|
|
15
|
+
|
|
16
|
+
- ``streaming`` — realtime / speech-to-speech protocols with a bespoke handshake. The
|
|
17
|
+
spec *selects* a protocol adapter; ``nova_sonic`` (Amazon Bedrock bidirectional S2S)
|
|
18
|
+
ships in :mod:`dreadnode.airt.targets.streaming`.
|
|
19
|
+
|
|
20
|
+
Module layout: :mod:`spec` (models) · :mod:`message` (payload conversion) ·
|
|
21
|
+
:mod:`auth` (auth strategies) · :mod:`http` (HTTP transport) · :mod:`streaming`
|
|
22
|
+
(streaming adapters) · :mod:`factory` (:func:`build_target` dispatcher).
|
|
23
|
+
|
|
24
|
+
Credentials are always read from environment variables / platform secrets — never
|
|
25
|
+
inlined into the spec.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
from dreadnode.airt.targets.factory import build_target
|
|
29
|
+
from dreadnode.airt.targets.spec import AuthType, TargetAuth, TargetSpec, Transport
|
|
30
|
+
from dreadnode.airt.targets.streaming import nova_sonic_target
|
|
31
|
+
|
|
32
|
+
__all__ = [
|
|
33
|
+
"AuthType",
|
|
34
|
+
"TargetAuth",
|
|
35
|
+
"TargetSpec",
|
|
36
|
+
"Transport",
|
|
37
|
+
"build_target",
|
|
38
|
+
"nova_sonic_target",
|
|
39
|
+
]
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"""HTTP authentication strategies.
|
|
2
|
+
|
|
3
|
+
Each auth mode reads its credential/identity from the environment or the platform's
|
|
4
|
+
credential chain — never from the spec. Provider SDKs (boto3, azure-identity,
|
|
5
|
+
google-auth) are imported dynamically so they stay off the SDK's hard-dependency set.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import importlib
|
|
9
|
+
import os
|
|
10
|
+
|
|
11
|
+
from dreadnode.airt.targets.spec import TargetSpec
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def apply_auth(
|
|
15
|
+
spec: TargetSpec, headers: dict[str, str], url: str, content: bytes
|
|
16
|
+
) -> dict[str, str]:
|
|
17
|
+
"""Return the request headers with the spec's auth applied.
|
|
18
|
+
|
|
19
|
+
For ``aws_sigv4`` the returned dict is the fully signed header set (which depends on
|
|
20
|
+
``url`` and ``content``); every other mode just adds an authorization header.
|
|
21
|
+
"""
|
|
22
|
+
auth = spec.auth
|
|
23
|
+
headers = dict(headers)
|
|
24
|
+
if auth.type == "api_key":
|
|
25
|
+
headers[auth.header] = auth.value_prefix + os.environ.get(auth.env_var, "")
|
|
26
|
+
elif auth.type == "bearer":
|
|
27
|
+
headers["Authorization"] = "Bearer " + os.environ.get(auth.env_var, "")
|
|
28
|
+
elif auth.type == "azure_ad":
|
|
29
|
+
headers["Authorization"] = "Bearer " + azure_ad_token(auth.scope)
|
|
30
|
+
elif auth.type == "gcp":
|
|
31
|
+
headers["Authorization"] = "Bearer " + gcp_token(auth.scope)
|
|
32
|
+
elif auth.type == "aws_sigv4":
|
|
33
|
+
headers = sign_sigv4(url, content, headers, auth.region, auth.service)
|
|
34
|
+
return headers
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def sign_sigv4(
|
|
38
|
+
url: str, body: bytes, headers: dict[str, str], region: str, service: str
|
|
39
|
+
) -> dict[str, str]:
|
|
40
|
+
"""Sign a POST with AWS SigV4 using the default credential chain (env/profile/role)."""
|
|
41
|
+
boto3 = importlib.import_module("boto3")
|
|
42
|
+
sigv4_auth = importlib.import_module("botocore.auth").SigV4Auth
|
|
43
|
+
aws_request = importlib.import_module("botocore.awsrequest").AWSRequest
|
|
44
|
+
|
|
45
|
+
creds = boto3.Session().get_credentials()
|
|
46
|
+
if creds is None:
|
|
47
|
+
raise RuntimeError("aws_sigv4 auth requires AWS credentials (env vars, profile, or role)")
|
|
48
|
+
req = aws_request(method="POST", url=url, data=body, headers=headers)
|
|
49
|
+
sigv4_auth(creds.get_frozen_credentials(), service, region).add_auth(req)
|
|
50
|
+
return dict(req.headers)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def azure_ad_token(scope: str) -> str:
|
|
54
|
+
"""Acquire an Entra token via DefaultAzureCredential (managed identity, workload
|
|
55
|
+
identity, env creds, or ``az login`` — in that precedence)."""
|
|
56
|
+
default_azure_credential = importlib.import_module("azure.identity").DefaultAzureCredential
|
|
57
|
+
|
|
58
|
+
return default_azure_credential().get_token(scope).token
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def gcp_token(scope: str) -> str:
|
|
62
|
+
"""Acquire a token via Google Application Default Credentials (service account,
|
|
63
|
+
workload identity, or ``gcloud`` login)."""
|
|
64
|
+
google_auth = importlib.import_module("google.auth")
|
|
65
|
+
request_cls = importlib.import_module("google.auth.transport.requests").Request
|
|
66
|
+
|
|
67
|
+
scopes = (
|
|
68
|
+
[scope]
|
|
69
|
+
if scope and scope.startswith("http")
|
|
70
|
+
else ["https://www.googleapis.com/auth/cloud-platform"]
|
|
71
|
+
)
|
|
72
|
+
creds, _ = google_auth.default(scopes=scopes)
|
|
73
|
+
creds.refresh(request_cls())
|
|
74
|
+
return creds.token
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""Dispatcher: turn a declarative :class:`TargetSpec` into a runnable ``@task``."""
|
|
2
|
+
|
|
3
|
+
import typing as t
|
|
4
|
+
|
|
5
|
+
from dreadnode.airt.targets.http import http_target
|
|
6
|
+
from dreadnode.airt.targets.spec import TargetSpec
|
|
7
|
+
from dreadnode.airt.targets.streaming.nova_sonic import nova_sonic_target
|
|
8
|
+
from dreadnode.core.task import Task
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def build_target(spec: TargetSpec) -> Task[..., t.Any]:
|
|
12
|
+
"""Build a dreadnode ``@task`` target from a :class:`TargetSpec`.
|
|
13
|
+
|
|
14
|
+
Example (HTTP, Azure AI Foundry)::
|
|
15
|
+
|
|
16
|
+
target = build_target(TargetSpec(
|
|
17
|
+
endpoint="https://my.westus.inference.ml.azure.com/score",
|
|
18
|
+
auth=TargetAuth(type="api_key", header="Authorization", value_prefix="Bearer ",
|
|
19
|
+
env_var="AZURE_FOUNDRY_KEY"),
|
|
20
|
+
request_template='{"input_data": {"input_string": ["{prompt}"]}}',
|
|
21
|
+
response_text_path="$.output",
|
|
22
|
+
))
|
|
23
|
+
|
|
24
|
+
Example (streaming, Amazon Nova Sonic S2S)::
|
|
25
|
+
|
|
26
|
+
target = build_target(TargetSpec(
|
|
27
|
+
transport="streaming", protocol="nova_sonic", endpoint="us-east-1",
|
|
28
|
+
options={"voice": "matthew"},
|
|
29
|
+
))
|
|
30
|
+
"""
|
|
31
|
+
if spec.transport == "http":
|
|
32
|
+
return http_target(spec)
|
|
33
|
+
if spec.transport == "streaming":
|
|
34
|
+
if spec.protocol == "nova_sonic":
|
|
35
|
+
return nova_sonic_target(
|
|
36
|
+
region=spec.endpoint or "us-east-1", name=spec.name, **spec.options
|
|
37
|
+
)
|
|
38
|
+
raise ValueError(f"Unknown streaming protocol: {spec.protocol!r}")
|
|
39
|
+
raise ValueError(f"Unknown transport: {spec.transport!r}")
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"""HTTP request/response transport: declarative body template + JSONPath response."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
|
|
5
|
+
import httpx
|
|
6
|
+
|
|
7
|
+
from dreadnode.airt.targets.auth import apply_auth
|
|
8
|
+
from dreadnode.airt.targets.message import extract_parts, extract_response_text
|
|
9
|
+
from dreadnode.airt.targets.spec import TargetSpec
|
|
10
|
+
from dreadnode.core.task import Task, task
|
|
11
|
+
from dreadnode.generators.message import Message
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _render_body(template: str, parts: dict[str, str]) -> dict:
|
|
15
|
+
body_str = template
|
|
16
|
+
for key, value in parts.items():
|
|
17
|
+
token = "{" + key + "}"
|
|
18
|
+
# JSON-escape the (untrusted) prompt; base64 is already safe.
|
|
19
|
+
replacement = json.dumps(value)[1:-1] if key == "prompt" else value
|
|
20
|
+
body_str = body_str.replace(token, replacement)
|
|
21
|
+
return json.loads(body_str)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
async def http_call(message: Message, spec: TargetSpec) -> str:
|
|
25
|
+
"""Serialize the message, POST it to the endpoint with auth, and extract the reply.
|
|
26
|
+
|
|
27
|
+
Kept free of the ``@task`` wrapper so the request/response logic is unit testable
|
|
28
|
+
without the tracing/storage a Task invocation requires.
|
|
29
|
+
"""
|
|
30
|
+
body = _render_body(spec.request_template, extract_parts(message))
|
|
31
|
+
content = json.dumps(body).encode("utf-8")
|
|
32
|
+
headers = apply_auth(spec, {"Content-Type": "application/json"}, spec.endpoint, content)
|
|
33
|
+
|
|
34
|
+
async with httpx.AsyncClient(timeout=spec.timeout_s) as client:
|
|
35
|
+
resp = await client.post(spec.endpoint, content=content, headers=headers)
|
|
36
|
+
resp.raise_for_status()
|
|
37
|
+
data = resp.json()
|
|
38
|
+
return extract_response_text(data, spec.response_text_path)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def http_target(spec: TargetSpec) -> Task[..., str]:
|
|
42
|
+
async def target(message: Message) -> str:
|
|
43
|
+
return await http_call(message, spec)
|
|
44
|
+
|
|
45
|
+
return task(target, name=spec.name)
|