dreadnode 2.0.35__tar.gz → 2.0.36__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.35 → dreadnode-2.0.36}/PKG-INFO +4 -1
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/agents/agent.py +35 -1
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/__init__.py +74 -0
- dreadnode-2.0.36/dreadnode/airt/_base.py +213 -0
- dreadnode-2.0.36/dreadnode/airt/art_engine.py +183 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/assessment.py +11 -1
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/crescendo.py +8 -4
- dreadnode-2.0.36/dreadnode/airt/evasion/__init__.py +46 -0
- dreadnode-2.0.36/dreadnode/airt/evasion/_base.py +399 -0
- dreadnode-2.0.36/dreadnode/airt/evasion/_text_common.py +198 -0
- dreadnode-2.0.36/dreadnode/airt/evasion/bae.py +62 -0
- dreadnode-2.0.36/dreadnode/airt/evasion/boundary.py +57 -0
- dreadnode-2.0.36/dreadnode/airt/evasion/deepwordbug.py +72 -0
- dreadnode-2.0.36/dreadnode/airt/evasion/hopskipjump.py +86 -0
- dreadnode-2.0.36/dreadnode/airt/evasion/pwws.py +112 -0
- dreadnode-2.0.36/dreadnode/airt/evasion/simba.py +67 -0
- dreadnode-2.0.36/dreadnode/airt/evasion/square.py +73 -0
- dreadnode-2.0.36/dreadnode/airt/evasion/text.py +90 -0
- dreadnode-2.0.36/dreadnode/airt/evasion/textbugger.py +69 -0
- dreadnode-2.0.36/dreadnode/airt/evasion/textfooler.py +48 -0
- dreadnode-2.0.36/dreadnode/airt/evasion/zoo.py +83 -0
- dreadnode-2.0.36/dreadnode/airt/extraction/__init__.py +63 -0
- dreadnode-2.0.36/dreadnode/airt/extraction/_base.py +703 -0
- dreadnode-2.0.36/dreadnode/airt/extraction/activethief.py +108 -0
- dreadnode-2.0.36/dreadnode/airt/extraction/copycat.py +32 -0
- dreadnode-2.0.36/dreadnode/airt/extraction/distillation.py +35 -0
- dreadnode-2.0.36/dreadnode/airt/extraction/equation_solving.py +34 -0
- dreadnode-2.0.36/dreadnode/airt/extraction/jacobian.py +82 -0
- dreadnode-2.0.36/dreadnode/airt/extraction/knockoff.py +34 -0
- dreadnode-2.0.36/dreadnode/airt/inversion/__init__.py +32 -0
- dreadnode-2.0.36/dreadnode/airt/inversion/_base.py +262 -0
- dreadnode-2.0.36/dreadnode/airt/inversion/confidence.py +80 -0
- dreadnode-2.0.36/dreadnode/airt/inversion/nes_inversion.py +100 -0
- dreadnode-2.0.36/dreadnode/airt/membership/__init__.py +59 -0
- dreadnode-2.0.36/dreadnode/airt/membership/_base.py +416 -0
- dreadnode-2.0.36/dreadnode/airt/membership/entropy.py +30 -0
- dreadnode-2.0.36/dreadnode/airt/membership/label_only.py +86 -0
- dreadnode-2.0.36/dreadnode/airt/membership/lira.py +83 -0
- dreadnode-2.0.36/dreadnode/airt/membership/loss.py +30 -0
- dreadnode-2.0.36/dreadnode/airt/membership/shadow_model.py +85 -0
- dreadnode-2.0.36/dreadnode/airt/membership/threshold.py +148 -0
- dreadnode-2.0.36/dreadnode/airt/model_export.py +129 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/targets/__init__.py +12 -0
- dreadnode-2.0.36/dreadnode/airt/targets/prediction.py +211 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/api/models.py +24 -1
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/cli/airt.py +291 -5
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/cli/args.py +8 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/cli/capability.py +18 -5
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/cli/evaluation.py +91 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/cli/main.py +2 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/client/managed_client.py +2 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/client/models.py +2 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/client/runtime_client.py +63 -9
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/main.py +18 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/print_mode.py +7 -1
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/server/app.py +146 -10
- dreadnode-2.0.36/dreadnode/app/server/auth.py +120 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/server/capability_manager.py +50 -1
- dreadnode-2.0.36/dreadnode/app/server/runtime_token.py +395 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/server/session_hydrator.py +44 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/server/websocket.py +192 -21
- dreadnode-2.0.36/dreadnode/app/server/ws_auth.py +111 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/app.py +85 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/screens/capabilities.py +15 -2
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/screens/models.py +5 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/sessions_manager.py +97 -5
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/turn_coordinator.py +14 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/conversation.py +38 -1
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/tool.py +21 -3
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/agent-output.md +5 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/dependencies-and-checks.md +3 -3
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/hooks.md +20 -1
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/policies.md +21 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/tools.md +21 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/sdk/capabilities.md +1 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/tui/default-tools.md +11 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/airt.md +26 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/evaluation.md +5 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/capabilities/install.py +79 -11
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/capabilities/loader.py +404 -46
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/core/environment.py +6 -1
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/generators/proxy.py +57 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/optimization/study.py +31 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/tracing/constants.py +26 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/transforms/language.py +18 -9
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/transforms/refine.py +9 -4
- {dreadnode-2.0.35 → dreadnode-2.0.36}/pyproject.toml +26 -2
- dreadnode-2.0.35/dreadnode/app/server/auth.py +0 -66
- dreadnode-2.0.35/dreadnode/app/server/ws_auth.py +0 -76
- {dreadnode-2.0.35 → dreadnode-2.0.36}/.gitignore +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/LICENSE +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/README.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/__main__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/agents/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/agents/engines/AGENTS.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/agents/engines/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/agents/engines/base.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/agents/engines/claude_code.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/agents/engines/native.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/agents/events.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/agents/exceptions.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/agents/format.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/agents/hooks.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/agents/judge.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/agents/mcp/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/agents/mcp/auth.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/agents/mcp/client.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/agents/mcp/config.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/agents/mcp/server.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/agents/process_judge.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/agents/reactions.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/agents/sanitize.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/agents/skills.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/agents/stopping.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/agents/subagent.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/agents/tool_resolution.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/agents/tools.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/agents/trajectory.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/adversarial_reasoning.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/advpromptier.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/alignment_faking.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/analogy_escalation.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/analytics/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/analytics/aggregator.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/analytics/classifier.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/analytics/compliance.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/analytics/engine.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/analytics/recommendations.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/analytics/types.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/aprt_progressive.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/atlas/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/atlas/defense.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/atlas/failure.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/atlas/gate.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/atlas/memory.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/atlas/modes.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/atlas/probes.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/atlas/recon.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/atlas/router.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/atlas/strategy.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/attention_shifting.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/autodan_turbo.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/autoredteamer.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/beast.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/compliance/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/compliance/atlas.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/compliance/nist.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/compliance/owasp.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/compliance/owasp_agentic.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/compliance/saif.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/constants.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/cot_jailbreak.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/data/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/data/assets/audio/adversarial_query.mp3 +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/data/assets/image/bomb.jpg +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/data/assets/image/meth.png +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/data/prompts/adversarial_benchmark_subset.csv +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/data/prompts/ai_safety.csv +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/data/rubrics/data_exfiltration.yaml +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/data/rubrics/goal_hijacking.yaml +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/data/rubrics/idor.yaml +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/data/rubrics/memory_poisoning.yaml +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/data/rubrics/privilege_escalation.yaml +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/data/rubrics/rce.yaml +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/data/rubrics/scope_creep.yaml +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/data/rubrics/tool_chaining.yaml +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/data/rubrics/tool_selection_safety.yaml +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/data/rubrics/unbounded_agency.yaml +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/data/rubrics/web_chatbot_security.yaml +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/data/templates/crescendo/variant_1.yaml +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/data/templates/crescendo/variant_2.yaml +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/data/templates/crescendo/variant_3.yaml +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/data/templates/crescendo/variant_4.yaml +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/data/templates/crescendo/variant_5.yaml +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/deep_inception.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/drattack.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/echo_chamber.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/events.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/genetic_persona.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/goat.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/goat_v2.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/gptfuzzer.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/humor_bypass.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/image.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/j2_meta.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/jbdistill.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/jbfuzz.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/lrm_autonomous.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/mapf.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/message_parts.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/multimodal.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/nexus.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/pair.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/persona_hijack.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/prompt.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/quantization_safety.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/rainbow.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/refusal_aware.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/renellm.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/reporting/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/reporting/json_report.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/reporting/llm_summary.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/reporting/markdown.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/reward_hacking.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/salami_slicing.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/self_persuasion.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/siren.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/tap.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/target.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/targets/auth.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/targets/factory.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/targets/http.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/targets/message.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/targets/spec.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/targets/streaming/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/targets/streaming/nova_sonic.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/templatefuzz.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/tmap_trajectory.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/trojail.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/airt/watermark_removal.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/api/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/api/client.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/cli/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/cli/dataset.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/cli/environment.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/cli/inference_model.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/cli/judge.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/cli/model.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/cli/optimize.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/cli/runtime.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/cli/sandbox.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/cli/secret.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/cli/session.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/cli/shared.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/cli/task.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/cli/task_set.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/cli/templates/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/cli/templates/init/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/cli/templates/init/challenge/Dockerfile +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/cli/templates/init/docker-compose.yaml +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/cli/templates/init/provision.sh +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/cli/templates/init/solution.sh +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/cli/templates/init/task-remote.yaml.tmpl +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/cli/templates/init/task.yaml.tmpl +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/cli/templates/init/teardown.sh +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/cli/templates/init/verify.sh +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/cli/train.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/cli/worlds.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/client/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/client/interactive.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/client/transports.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/config.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/env.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/model_catalog.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/paths.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/server/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/server/model_resolution.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/server/prompt.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/server/prompt_registry.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/server/runtime_events.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/server/session_persistence.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/server/turn_coordinator.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/server/utils.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/server/worker_manager.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/auth_flow.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/capabilities_manager.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/command_dispatcher.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/commands.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/connection.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/dreadnode.tcss +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/error_handler.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/model_manager.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/model_variants.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/profile_manager.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/runtime_cache.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/screen_router.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/screens/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/screens/auth.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/screens/base.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/screens/capability_docs.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/screens/connection_error.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/screens/console.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/screens/environments.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/screens/evaluations.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/screens/raw_spans.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/screens/readme.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/screens/runtimes.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/screens/sandboxes.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/screens/secrets.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/screens/services.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/screens/sessions.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/screens/theme_showcase.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/screens/traces.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/screens/workspaces.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/spans_reader.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/status_messages.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/theme.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/tool_format.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/turn_lifecycle.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/turn_reducer.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/turn_state_phase.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/update_check.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/agent_dialog.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/agent_suggester.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/composer.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/confirm_modal.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/context_bar.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/flash.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/header_bar.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/help_panel.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/human_prompt.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/mention_overlay.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/message_queue.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/new_messages_pill.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/overlay_mixin.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/permission_prompt.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/profile_dialog.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/prompt_info.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/rewind_picker.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/session_sidebar.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/skills_dialog.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/slash_overlay.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/status_bar.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/throbber.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/tool_progress.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/tools_dialog.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/welcome.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/whoami.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/app/tui/wire_events.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/MAINTAINING.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/agents/dreadnode.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/capability.yaml +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/SKILL.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/capability-improvement.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/methodology-grounding.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/prior-art-audit.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/promoting-capabilities.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/quality-bar.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/INDEX.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/agents.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/custom-engines.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/engines.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/env-vars.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/events.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/flags.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/installing.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/manifest.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/mcp-servers.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/overview.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/publishing.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/quickstart.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/skills.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/workers-reference.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/workers.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/writing-skills.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/sdk/agents.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references-and-depth.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/runtime-default-capability.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/SKILL.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/INDEX.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/capability.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/dataset.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/env.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/inference-model.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/main.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/model.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/optimize.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/overview.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/runtime.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/sandbox.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/secret.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/task-set.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/task.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/train.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/worlds.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/getting-started/authentication.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/SKILL.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/INDEX.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/capabilities/installing.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/capabilities/overview.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/getting-started/authentication.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/getting-started/overview.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/getting-started/quickstart.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/chat-models.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/credits.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/organizations.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/overview.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/projects.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/secrets.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/settings.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/workspaces.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/runtimes/configuration.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/runtimes/managing.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/runtimes/manifest-reference.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/runtimes/overview.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/runtimes/quickstart.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/runtimes/serve.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/sandboxes/environment-lifecycle.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/sandboxes/inspecting.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/sandboxes/overview.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/sandboxes/runtime-limits.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/getting-started/SKILL.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/research-capabilities/SKILL.md +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/self-improvement/.gitignore +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/self-improvement/capability.yaml +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/self-improvement/hooks/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/self-improvement/hooks/observer.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/self-improvement/self_improvement_lib/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/self-improvement/self_improvement_lib/classifier.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/self-improvement/self_improvement_lib/reflector_goal.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/self-improvement/self_improvement_lib/skill_io.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/self-improvement/skills-promoted/.gitkeep +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/self-improvement/skills-proposed/.gitkeep +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/self-improvement/tools/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/self-improvement/tools/reflector.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/self-improvement/tools/skill_stats.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/capabilities/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/capabilities/capability.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/capabilities/flags.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/capabilities/sync.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/capabilities/tool_rules.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/capabilities/types.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/capabilities/worker.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/capabilities/worker_runner.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/core/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/core/conditions.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/core/discovery.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/core/exceptions.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/core/execution.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/core/hook.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/core/judge.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/core/load.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/core/log.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/core/meta/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/core/meta/config.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/core/meta/context.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/core/meta/hydrate.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/core/meta/introspect.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/core/metric.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/core/object.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/core/scorer.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/core/serialization.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/core/stopping.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/core/task.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/core/templating.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/core/transforms.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/core/types/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/core/types/audio.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/core/types/base.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/core/types/common.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/core/types/image.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/core/types/object_3d.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/core/types/table.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/core/types/text.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/core/types/video.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/core/util.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/datasets/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/datasets/dataset.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/datasets/hf.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/datasets/local.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/evaluations/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/evaluations/console.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/evaluations/evaluation.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/evaluations/events.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/evaluations/format.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/evaluations/result.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/evaluations/sample.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/generators/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/generators/caching.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/generators/chat.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/generators/data.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/generators/exceptions.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/generators/generator/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/generators/generator/base.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/generators/generator/http.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/generators/generator/litellm_.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/generators/generator/transformers_.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/generators/generator/vllm_.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/generators/message.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/generators/models.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/generators/parsing.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/generators/tokenizer/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/generators/tokenizer/base.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/generators/tokenizer/transformers_.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/generators/utils.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/items/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/items/config.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/items/models.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/judges/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/judges/outcome.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/judges/trajectory.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/judges/trajectory_tools.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/models/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/models/hf.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/models/local.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/models/model.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/optimization/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/optimization/adapters/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/optimization/adapters/_env_eval.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/optimization/adapters/agent.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/optimization/adapters/env.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/optimization/adapters/runtime.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/optimization/adapters/stack.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/optimization/api.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/optimization/backends/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/optimization/backends/base.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/optimization/backends/gepa.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/optimization/collectors.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/optimization/config.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/optimization/console.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/optimization/events.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/optimization/format.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/optimization/jobs.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/optimization/result.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/optimization/sampler.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/optimization/sampling.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/optimization/search.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/optimization/stopping.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/optimization/trial.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/packaging/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/packaging/loader.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/packaging/manifest.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/packaging/oci.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/packaging/package.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/packaging/task_validation.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/policies/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/policies/guard.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/policies/reconciliation.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/policies/rubrics/process/default.yaml +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/py.typed +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/samplers/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/samplers/boundary.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/samplers/fuzzing.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/samplers/graph.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/samplers/grid.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/samplers/image.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/samplers/mapelites.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/samplers/optuna.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/samplers/random.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/samplers/registry.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/samplers/strategy.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/scorers/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/scorers/advanced_jailbreak_detection.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/scorers/agent_security.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/scorers/agentic.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/scorers/agentic_workflow.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/scorers/attack_outcome.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/scorers/classification.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/scorers/consistency.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/scorers/contains.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/scorers/cosine_sim.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/scorers/credentials.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/scorers/crucible.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/scorers/documentation_security.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/scorers/exfiltration_detection.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/scorers/format.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/scorers/harm.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/scorers/ide_security.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/scorers/image.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/scorers/json.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/scorers/judge.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/scorers/judge_ensemble.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/scorers/length.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/scorers/lexical.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/scorers/mcp_security.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/scorers/memorization.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/scorers/multi_agent_security.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/scorers/pii.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/scorers/prompt_leak.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/scorers/readability.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/scorers/reasoning_security.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/scorers/sentiment.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/scorers/similarity.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/scorers/structural_detection.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/scorers/supply_chain_detection.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/storage/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/storage/providers.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/storage/session_store.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/storage/storage.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/tools/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/tools/_ripgrep.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/tools/apply_patch.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/tools/dreadnode_cli.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/tools/editing.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/tools/execute.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/tools/fetch.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/tools/glob.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/tools/grep.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/tools/interaction.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/tools/ls.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/tools/memory.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/tools/project_memory.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/tools/read.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/tools/report.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/tools/report_items.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/tools/task.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/tools/think.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/tools/todo.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/tools/trajectory_search.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/tools/web_extract.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/tools/web_search.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/tools/write.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/tracing/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/tracing/convert.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/tracing/exporter.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/tracing/exporters.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/tracing/span.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/tracing/spans.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/tracing/trace_converter.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/_progress.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/base.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/dpo.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/env_rollouts.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/etl/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/etl/_common.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/etl/rl.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/etl/sft.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/etl/worlds.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/events.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/grpo.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/jobs.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/models.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/ppo.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/prime.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/ray/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/ray/async_trainer.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/ray/config.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/ray/coordinator.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/ray/distributed.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/ray/dpo.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/ray/experience.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/ray/fsdp2_learner.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/ray/inference.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/ray/learner.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/ray/multi_turn.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/ray/ppo.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/ray/reward_model.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/ray/rollout_env.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/ray/rollout_worker.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/ray/sft.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/ray/trainer.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/recipes.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/rewards/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/rewards/aggregator.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/rewards/functions.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/rewards/scorer_bridge.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/rewards/shaping.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/rewards/types.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/rollouts/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/rollouts/adapters.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/rollouts/agent_rollout.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/rollouts/orchestrator.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/rollouts/types.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/rollouts/worlds.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/serving/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/serving/vllm_client.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/sft.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/tinker/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/tinker/config.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/tinker/data.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/tinker/renderer.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/tinker/rl.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/tinker/trainer.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/tinker_sft.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/training/utils.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/transforms/__init__.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/transforms/advanced_jailbreak.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/transforms/adversarial_suffix.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/transforms/agent_skill.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/transforms/agentic_workflow.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/transforms/audio.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/transforms/backdoor_finetune.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/transforms/browser_agent_attacks.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/transforms/cipher.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/transforms/competitive_parity.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/transforms/constitutional.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/transforms/document.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/transforms/documentation_poison.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/transforms/encoding.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/transforms/exfiltration.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/transforms/flip_attack.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/transforms/guardrail_bypass.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/transforms/ide_injection.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/transforms/image.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/transforms/injection.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/transforms/json_tools.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/transforms/logic_bomb.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/transforms/mcp_attacks.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/transforms/multi_agent_attacks.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/transforms/multimodal_attacks.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/transforms/persuasion.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/transforms/perturbation.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/transforms/pii_extraction.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/transforms/pythonic_tools.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/transforms/rag_poisoning.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/transforms/reasoning_attacks.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/transforms/response_steering.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/transforms/structural_exploits.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/transforms/stylistic.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/transforms/substitution.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/transforms/supply_chain.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/transforms/swap.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/transforms/system_prompt_extraction.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/transforms/text.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/transforms/video.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/transforms/xml_tools.py +0 -0
- {dreadnode-2.0.35 → dreadnode-2.0.36}/dreadnode/version.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dreadnode
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.36
|
|
4
4
|
Summary: Dreadnode SDK
|
|
5
5
|
Project-URL: Homepage, https://dreadnode.io
|
|
6
6
|
Project-URL: Documentation, https://docs.dreadnode.io
|
|
@@ -51,6 +51,9 @@ Requires-Dist: transformers>=4.57.1
|
|
|
51
51
|
Requires-Dist: uvicorn>=0.34.0
|
|
52
52
|
Requires-Dist: websockets>=14.0
|
|
53
53
|
Requires-Dist: xmltodict>=1.0.2
|
|
54
|
+
Provides-Extra: airt-ml
|
|
55
|
+
Requires-Dist: scikit-learn<2.0.0,>=1.7.1; extra == 'airt-ml'
|
|
56
|
+
Requires-Dist: torch>=2.9.0; extra == 'airt-ml'
|
|
54
57
|
Provides-Extra: all
|
|
55
58
|
Requires-Dist: confusables<2.0.0,>=1.2.0; extra == 'all'
|
|
56
59
|
Requires-Dist: moviepy<3.0.0,>=2.1.2; extra == 'all'
|
|
@@ -133,6 +133,31 @@ def _is_transient_api_error(error: BaseException) -> bool:
|
|
|
133
133
|
return False
|
|
134
134
|
|
|
135
135
|
|
|
136
|
+
def _replayable(messages: list[Message]) -> list[Message]:
|
|
137
|
+
"""Drop assistant messages that carry nothing worth sending back.
|
|
138
|
+
|
|
139
|
+
A generation stopped by a content filter leaves an empty assistant message.
|
|
140
|
+
The trajectory keeps it — it is the record of what the provider did, and
|
|
141
|
+
the transcript renders a warning from it — but replaying it on the next
|
|
142
|
+
turn sends an empty text block, which some providers reject outright
|
|
143
|
+
(see ``CacheControlOnEmptyTextFixup``) and none can use (ENG-7585).
|
|
144
|
+
|
|
145
|
+
Reasoning lives in ``metadata``, not ``content``, so a thinking-only
|
|
146
|
+
message is still replayable and must survive this filter.
|
|
147
|
+
"""
|
|
148
|
+
|
|
149
|
+
def carries_nothing(message: Message) -> bool:
|
|
150
|
+
return (
|
|
151
|
+
message.role == "assistant"
|
|
152
|
+
and not message.content
|
|
153
|
+
and not message.tool_calls
|
|
154
|
+
and not message.metadata.get("reasoning_content")
|
|
155
|
+
and not message.metadata.get("thinking_blocks")
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
return [message for message in messages if not carries_nothing(message)]
|
|
159
|
+
|
|
160
|
+
|
|
136
161
|
class Agent(Executor[AgentEvent, Trajectory]):
|
|
137
162
|
"""
|
|
138
163
|
Agent abstraction for applying tools, event logic, and message state to LLM generation.
|
|
@@ -776,7 +801,7 @@ class Agent(Executor[AgentEvent, Trajectory]):
|
|
|
776
801
|
"""
|
|
777
802
|
traj = trajectory if trajectory is not None else self.trajectory
|
|
778
803
|
messages = [
|
|
779
|
-
*deepcopy(traj.messages),
|
|
804
|
+
*_replayable(deepcopy(traj.messages)),
|
|
780
805
|
Message(
|
|
781
806
|
"user",
|
|
782
807
|
str(self._current_input),
|
|
@@ -925,6 +950,15 @@ class Agent(Executor[AgentEvent, Trajectory]):
|
|
|
925
950
|
break
|
|
926
951
|
|
|
927
952
|
step_chat.generated[-1].metadata.update(step_chat.extra)
|
|
953
|
+
# The provider's stop reason belongs to the assistant
|
|
954
|
+
# message, not to a particular event stream — stamping it
|
|
955
|
+
# here (before any event is dispatched) lets hooks,
|
|
956
|
+
# transcript reloads and non-live consumers all recover the
|
|
957
|
+
# same outcome live GenerationEnd observers see (ENG-7585).
|
|
958
|
+
if step_chat.stop_reason:
|
|
959
|
+
step_chat.generated[-1].metadata["generation_stop_reason"] = (
|
|
960
|
+
step_chat.stop_reason
|
|
961
|
+
)
|
|
928
962
|
for msg in step_chat.generated:
|
|
929
963
|
msg.metadata.setdefault("agent", self.name)
|
|
930
964
|
msg.metadata.setdefault("model", self.model_name)
|
|
@@ -54,6 +54,16 @@ Image adversarial attacks:
|
|
|
54
54
|
|
|
55
55
|
Multimodal attacks:
|
|
56
56
|
- multimodal_attack: Transform-based multimodal probing (vision, audio, text)
|
|
57
|
+
|
|
58
|
+
Traditional-ML attacks (query a classifier predict API via PredictionTargetSpec):
|
|
59
|
+
- equation_solving_extraction: linear-model weight recovery (Tramèr'16)
|
|
60
|
+
- jacobian_extraction: Jacobian dataset augmentation (Papernot'17)
|
|
61
|
+
- copycat_extraction: hard-label distillation (CopycatCNN)
|
|
62
|
+
- knockoff_extraction: soft-label transfer-set extraction (Knockoff Nets)
|
|
63
|
+
- threshold_membership: confidence/entropy/loss-threshold membership inference (Yeom'18)
|
|
64
|
+
- label_only_membership: label-only membership inference (Choquette-Choo'21)
|
|
65
|
+
- confidence_inversion: MI-Face confidence-maximizing model inversion (Fredrikson'15)
|
|
66
|
+
- nes_inversion: NES-based confidence-maximizing model inversion
|
|
57
67
|
"""
|
|
58
68
|
|
|
59
69
|
from dreadnode.airt.adversarial_reasoning import adversarial_reasoning_attack
|
|
@@ -72,6 +82,27 @@ from dreadnode.airt.crescendo import crescendo_attack
|
|
|
72
82
|
from dreadnode.airt.deep_inception import deep_inception_attack
|
|
73
83
|
from dreadnode.airt.drattack import drattack
|
|
74
84
|
from dreadnode.airt.echo_chamber import echo_chamber_attack
|
|
85
|
+
from dreadnode.airt.evasion import (
|
|
86
|
+
bae_evasion,
|
|
87
|
+
boundary_evasion,
|
|
88
|
+
deepwordbug_evasion,
|
|
89
|
+
hopskipjump_evasion,
|
|
90
|
+
pwws_evasion,
|
|
91
|
+
simba_evasion,
|
|
92
|
+
square_evasion,
|
|
93
|
+
text_evasion,
|
|
94
|
+
textbugger_evasion,
|
|
95
|
+
textfooler_evasion,
|
|
96
|
+
zoo_evasion,
|
|
97
|
+
)
|
|
98
|
+
from dreadnode.airt.extraction import (
|
|
99
|
+
activethief_extraction,
|
|
100
|
+
copycat_extraction,
|
|
101
|
+
distillation_extraction,
|
|
102
|
+
equation_solving_extraction,
|
|
103
|
+
jacobian_extraction,
|
|
104
|
+
knockoff_extraction,
|
|
105
|
+
)
|
|
75
106
|
from dreadnode.airt.genetic_persona import genetic_persona_attack
|
|
76
107
|
from dreadnode.airt.goat import goat_attack
|
|
77
108
|
from dreadnode.airt.goat_v2 import goat_v2_attack
|
|
@@ -83,11 +114,23 @@ from dreadnode.airt.image import (
|
|
|
83
114
|
simba_attack,
|
|
84
115
|
zoo_attack,
|
|
85
116
|
)
|
|
117
|
+
from dreadnode.airt.inversion import (
|
|
118
|
+
confidence_inversion,
|
|
119
|
+
nes_inversion,
|
|
120
|
+
)
|
|
86
121
|
from dreadnode.airt.j2_meta import j2_meta_attack
|
|
87
122
|
from dreadnode.airt.jbdistill import jbdistill_attack
|
|
88
123
|
from dreadnode.airt.jbfuzz import jbfuzz_attack
|
|
89
124
|
from dreadnode.airt.lrm_autonomous import lrm_autonomous_attack
|
|
90
125
|
from dreadnode.airt.mapf import mapf_attack
|
|
126
|
+
from dreadnode.airt.membership import (
|
|
127
|
+
entropy_membership,
|
|
128
|
+
label_only_membership,
|
|
129
|
+
lira_membership,
|
|
130
|
+
loss_membership,
|
|
131
|
+
shadow_model_membership,
|
|
132
|
+
threshold_membership,
|
|
133
|
+
)
|
|
91
134
|
from dreadnode.airt.multimodal import multimodal_attack
|
|
92
135
|
from dreadnode.airt.nexus import nexus_attack
|
|
93
136
|
from dreadnode.airt.pair import pair_attack
|
|
@@ -104,8 +147,11 @@ from dreadnode.airt.siren import siren_attack
|
|
|
104
147
|
from dreadnode.airt.tap import tap_attack
|
|
105
148
|
from dreadnode.airt.target import extract_response_text, extract_tool_calls
|
|
106
149
|
from dreadnode.airt.targets import (
|
|
150
|
+
Prediction,
|
|
151
|
+
PredictionTargetSpec,
|
|
107
152
|
TargetAuth,
|
|
108
153
|
TargetSpec,
|
|
154
|
+
build_prediction_target,
|
|
109
155
|
build_target,
|
|
110
156
|
nova_sonic_target,
|
|
111
157
|
)
|
|
@@ -116,8 +162,11 @@ from dreadnode.airt.watermark_removal import watermark_removal_attack
|
|
|
116
162
|
|
|
117
163
|
__all__ = [
|
|
118
164
|
"Assessment",
|
|
165
|
+
"Prediction",
|
|
166
|
+
"PredictionTargetSpec",
|
|
119
167
|
"TargetAuth",
|
|
120
168
|
"TargetSpec",
|
|
169
|
+
"activethief_extraction",
|
|
121
170
|
"adversarial_reasoning_attack",
|
|
122
171
|
"advpromptier_attack",
|
|
123
172
|
"alignment_faking_attack",
|
|
@@ -127,13 +176,22 @@ __all__ = [
|
|
|
127
176
|
"attention_shifting_attack",
|
|
128
177
|
"autodan_turbo_attack",
|
|
129
178
|
"autoredteamer_attack",
|
|
179
|
+
"bae_evasion",
|
|
130
180
|
"beast_attack",
|
|
181
|
+
"boundary_evasion",
|
|
182
|
+
"build_prediction_target",
|
|
131
183
|
"build_target",
|
|
184
|
+
"confidence_inversion",
|
|
185
|
+
"copycat_extraction",
|
|
132
186
|
"cot_jailbreak_attack",
|
|
133
187
|
"crescendo_attack",
|
|
134
188
|
"deep_inception_attack",
|
|
189
|
+
"deepwordbug_evasion",
|
|
190
|
+
"distillation_extraction",
|
|
135
191
|
"drattack",
|
|
136
192
|
"echo_chamber_attack",
|
|
193
|
+
"entropy_membership",
|
|
194
|
+
"equation_solving_extraction",
|
|
137
195
|
"extract_response_text",
|
|
138
196
|
"extract_tool_calls",
|
|
139
197
|
"genetic_persona_attack",
|
|
@@ -141,19 +199,27 @@ __all__ = [
|
|
|
141
199
|
"goat_v2_attack",
|
|
142
200
|
"gptfuzzer_attack",
|
|
143
201
|
"hopskipjump_attack",
|
|
202
|
+
"hopskipjump_evasion",
|
|
144
203
|
"humor_bypass_attack",
|
|
145
204
|
"j2_meta_attack",
|
|
205
|
+
"jacobian_extraction",
|
|
146
206
|
"jbdistill_attack",
|
|
147
207
|
"jbfuzz_attack",
|
|
208
|
+
"knockoff_extraction",
|
|
209
|
+
"label_only_membership",
|
|
210
|
+
"lira_membership",
|
|
211
|
+
"loss_membership",
|
|
148
212
|
"lrm_autonomous_attack",
|
|
149
213
|
"mapf_attack",
|
|
150
214
|
"multimodal_attack",
|
|
151
215
|
"nes_attack",
|
|
216
|
+
"nes_inversion",
|
|
152
217
|
"nexus_attack",
|
|
153
218
|
"nova_sonic_target",
|
|
154
219
|
"pair_attack",
|
|
155
220
|
"persona_hijack_attack",
|
|
156
221
|
"prompt_attack",
|
|
222
|
+
"pwws_evasion",
|
|
157
223
|
"quantization_safety_attack",
|
|
158
224
|
"rainbow_attack",
|
|
159
225
|
"refusal_aware_attack",
|
|
@@ -161,12 +227,20 @@ __all__ = [
|
|
|
161
227
|
"reward_hacking_attack",
|
|
162
228
|
"salami_slicing_attack",
|
|
163
229
|
"self_persuasion_attack",
|
|
230
|
+
"shadow_model_membership",
|
|
164
231
|
"simba_attack",
|
|
232
|
+
"simba_evasion",
|
|
165
233
|
"siren_attack",
|
|
234
|
+
"square_evasion",
|
|
166
235
|
"tap_attack",
|
|
167
236
|
"templatefuzz_attack",
|
|
237
|
+
"text_evasion",
|
|
238
|
+
"textbugger_evasion",
|
|
239
|
+
"textfooler_evasion",
|
|
240
|
+
"threshold_membership",
|
|
168
241
|
"tmap_trajectory_attack",
|
|
169
242
|
"trojail_attack",
|
|
170
243
|
"watermark_removal_attack",
|
|
171
244
|
"zoo_attack",
|
|
245
|
+
"zoo_evasion",
|
|
172
246
|
]
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
"""Shared base class for the black-box traditional-ML attacks.
|
|
2
|
+
|
|
3
|
+
Extraction, membership inference, and evasion all probe a black-box predict API
|
|
4
|
+
through the same :class:`PredictionTargetSpec` contract, count their queries,
|
|
5
|
+
capture a sample of the (input -> prediction) pairs they send, emit a top-level
|
|
6
|
+
``study`` span, and enforce a query budget. This module factors that shared
|
|
7
|
+
plumbing into :class:`BlackBoxAttack` so each family only implements its own
|
|
8
|
+
algorithm and its own result-to-span mapping.
|
|
9
|
+
|
|
10
|
+
The base also provides ``_trace_step`` - a capped per-iteration span that records
|
|
11
|
+
the intermediate adversarial state (distance, best score, candidate label /
|
|
12
|
+
confidence, queries so far). Because we own the algorithm loop, every step of the
|
|
13
|
+
attack trajectory is visible in the platform's Traces tab, which is exactly what
|
|
14
|
+
off-the-shelf frameworks (ART, TextAttack) make hard to surface.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
import typing as t
|
|
18
|
+
from contextlib import nullcontext, suppress
|
|
19
|
+
|
|
20
|
+
import numpy as np
|
|
21
|
+
|
|
22
|
+
from dreadnode.airt.targets.prediction import (
|
|
23
|
+
Prediction,
|
|
24
|
+
PredictionTargetSpec,
|
|
25
|
+
QueryInput,
|
|
26
|
+
predict_many,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@t.runtime_checkable
|
|
31
|
+
class AttackResult(t.Protocol):
|
|
32
|
+
"""The common surface every attack result exposes so :meth:`BlackBoxAttack.run`
|
|
33
|
+
can emit spans generically."""
|
|
34
|
+
|
|
35
|
+
query_samples: list[dict[str, t.Any]]
|
|
36
|
+
|
|
37
|
+
@property
|
|
38
|
+
def best_score(self) -> float: ...
|
|
39
|
+
|
|
40
|
+
@property
|
|
41
|
+
def metrics_detail(self) -> dict[str, t.Any]: ...
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def sample_input_preview(x: t.Any, n: int = 60) -> str:
|
|
45
|
+
"""A compact, display-safe preview of a queried input (text snippet or a few
|
|
46
|
+
numeric features) for the finding's query sample table."""
|
|
47
|
+
if isinstance(x, str):
|
|
48
|
+
return x if len(x) <= n else x[:n] + "..."
|
|
49
|
+
try:
|
|
50
|
+
arr = np.asarray(x, dtype=np.float64).ravel()
|
|
51
|
+
except Exception:
|
|
52
|
+
return str(x)[:n]
|
|
53
|
+
head = ", ".join(f"{v:.3g}" for v in arr[:6])
|
|
54
|
+
return f"[{head}{', ...' if arr.size > 6 else ''}] ({arr.size}d)"
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class BlackBoxAttack:
|
|
58
|
+
"""Base for a configured black-box attack against a predict API.
|
|
59
|
+
|
|
60
|
+
Subclasses set :attr:`attack_domain` (`model_extraction` /
|
|
61
|
+
`membership_inference` / `adversarial_ml`), a default goal, and implement
|
|
62
|
+
:meth:`_attack_name`, :meth:`_execute`, and :meth:`_span_attributes`. The
|
|
63
|
+
query counter, query-sample capture, phase/step tracing, and the top-level
|
|
64
|
+
``study`` span are shared here.
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
#: One of "model_extraction", "membership_inference", "adversarial_ml".
|
|
68
|
+
attack_domain: str = ""
|
|
69
|
+
default_goal: str = ""
|
|
70
|
+
default_goal_category: str = ""
|
|
71
|
+
|
|
72
|
+
def __init__(
|
|
73
|
+
self,
|
|
74
|
+
*,
|
|
75
|
+
target: PredictionTargetSpec,
|
|
76
|
+
modality: str = "tabular",
|
|
77
|
+
max_queries: int = 500,
|
|
78
|
+
max_iterations: int = 30,
|
|
79
|
+
seed: int | None = None,
|
|
80
|
+
airt_assessment_id: str | None = None,
|
|
81
|
+
airt_target_model: str | None = None,
|
|
82
|
+
airt_goal: str | None = None,
|
|
83
|
+
airt_goal_category: str | None = None,
|
|
84
|
+
) -> None:
|
|
85
|
+
self.target = target
|
|
86
|
+
self.modality = modality
|
|
87
|
+
self.max_queries = max_queries
|
|
88
|
+
self.max_iterations = max_iterations
|
|
89
|
+
self.rng = np.random.default_rng(seed)
|
|
90
|
+
self.airt_assessment_id = airt_assessment_id
|
|
91
|
+
self.airt_target_model = airt_target_model or target.name
|
|
92
|
+
self.airt_goal = airt_goal or self.default_goal
|
|
93
|
+
self.airt_goal_category = airt_goal_category or self.default_goal_category
|
|
94
|
+
self._query_count = 0
|
|
95
|
+
#: A sample of real (input -> prediction) pairs so the finding can show
|
|
96
|
+
#: the actual queries the attacker sent, not just the total count.
|
|
97
|
+
self._query_samples: list[dict[str, t.Any]] = []
|
|
98
|
+
|
|
99
|
+
# -- target I/O -------------------------------------------------------- #
|
|
100
|
+
async def _query(self, xs: t.Sequence[QueryInput]) -> list[Prediction]:
|
|
101
|
+
"""Query the target, count the queries, and capture a sample."""
|
|
102
|
+
preds = await predict_many(self.target, xs)
|
|
103
|
+
self._query_count += len(xs)
|
|
104
|
+
self._capture_samples(xs, preds)
|
|
105
|
+
return preds
|
|
106
|
+
|
|
107
|
+
def _capture_samples(
|
|
108
|
+
self, xs: t.Sequence[QueryInput], preds: t.Sequence[Prediction], limit: int = 12
|
|
109
|
+
) -> None:
|
|
110
|
+
for x, p in zip(xs, preds, strict=False):
|
|
111
|
+
if len(self._query_samples) >= limit:
|
|
112
|
+
return
|
|
113
|
+
vec = p.vector
|
|
114
|
+
conf = float(max(vec)) if vec is not None and len(vec) else None
|
|
115
|
+
self._query_samples.append(
|
|
116
|
+
{
|
|
117
|
+
"input": sample_input_preview(x),
|
|
118
|
+
"label": p.hard_label,
|
|
119
|
+
"confidence": round(conf, 4) if conf is not None else None,
|
|
120
|
+
}
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
# -- budget ------------------------------------------------------------ #
|
|
124
|
+
def _budget_left(self) -> int:
|
|
125
|
+
return max(0, self.max_queries - self._query_count)
|
|
126
|
+
|
|
127
|
+
def _over_budget(self) -> bool:
|
|
128
|
+
return self._query_count >= self.max_queries
|
|
129
|
+
|
|
130
|
+
# -- tracing ----------------------------------------------------------- #
|
|
131
|
+
def _phase(self, name: str, **attrs: t.Any) -> t.Any:
|
|
132
|
+
"""A coarse task-span phase (e.g. 'perturb + probe target')."""
|
|
133
|
+
try:
|
|
134
|
+
import dreadnode as dn
|
|
135
|
+
|
|
136
|
+
return dn.task_span(name, type="task", attributes={str(k): v for k, v in attrs.items()})
|
|
137
|
+
except Exception:
|
|
138
|
+
return nullcontext()
|
|
139
|
+
|
|
140
|
+
def _trace_step(
|
|
141
|
+
self,
|
|
142
|
+
iteration: int,
|
|
143
|
+
*,
|
|
144
|
+
input: t.Any = None,
|
|
145
|
+
output: t.Any = None,
|
|
146
|
+
metrics: dict[str, float] | None = None,
|
|
147
|
+
**attrs: t.Any,
|
|
148
|
+
) -> None:
|
|
149
|
+
"""Emit a point-in-time span for one algorithm iteration, recording the
|
|
150
|
+
intermediate adversarial state so the full attack trajectory is
|
|
151
|
+
inspectable in the Traces tab.
|
|
152
|
+
|
|
153
|
+
``input`` is the current candidate (perturbed text / feature vector /
|
|
154
|
+
image preview) the attacker sent; ``output`` is the target's response at
|
|
155
|
+
this step (predicted label + confidence); ``metrics`` are the scalar
|
|
156
|
+
signals (distance, confidence, fidelity) plotted over the run. Capped
|
|
157
|
+
(first 20 iterations, then every 10th) so a long run does not explode the
|
|
158
|
+
trace tree."""
|
|
159
|
+
if iteration >= 20 and iteration % 10 != 0:
|
|
160
|
+
return
|
|
161
|
+
with self._phase(f"step {iteration}", iteration=iteration, **attrs) as span:
|
|
162
|
+
if span is None or not hasattr(span, "log_input"):
|
|
163
|
+
return
|
|
164
|
+
with suppress(Exception):
|
|
165
|
+
if input is not None:
|
|
166
|
+
span.log_input("candidate", input)
|
|
167
|
+
if output is not None:
|
|
168
|
+
span.log_output("prediction", output)
|
|
169
|
+
for key, value in (metrics or {}).items():
|
|
170
|
+
span.log_metric(key, float(value), step=iteration)
|
|
171
|
+
|
|
172
|
+
# -- run scaffold ------------------------------------------------------ #
|
|
173
|
+
@property
|
|
174
|
+
def _attack_name(self) -> str:
|
|
175
|
+
raise NotImplementedError
|
|
176
|
+
|
|
177
|
+
def _study_kwargs(self) -> dict[str, t.Any]:
|
|
178
|
+
"""Extra ``study_span`` kwargs beyond the common set (e.g. distance norm)."""
|
|
179
|
+
return {}
|
|
180
|
+
|
|
181
|
+
def _span_attributes(self, result: t.Any) -> dict[str, t.Any]:
|
|
182
|
+
"""Map the result onto the ``AIRT_ATTRIBUTE_*`` span attributes to set.
|
|
183
|
+
``None`` values are skipped."""
|
|
184
|
+
raise NotImplementedError
|
|
185
|
+
|
|
186
|
+
async def _execute(self) -> t.Any:
|
|
187
|
+
raise NotImplementedError
|
|
188
|
+
|
|
189
|
+
async def run(self) -> t.Any:
|
|
190
|
+
import json
|
|
191
|
+
|
|
192
|
+
from dreadnode.tracing.constants import AIRT_ATTRIBUTE_METRICS_DETAIL
|
|
193
|
+
from dreadnode.tracing.spans import study_span
|
|
194
|
+
|
|
195
|
+
with study_span(
|
|
196
|
+
name=self._attack_name,
|
|
197
|
+
airt_assessment_id=self.airt_assessment_id,
|
|
198
|
+
airt_attack_name=self._attack_name,
|
|
199
|
+
airt_attack_domain=self.attack_domain,
|
|
200
|
+
airt_target_model=self.airt_target_model,
|
|
201
|
+
airt_input_modality=self.modality,
|
|
202
|
+
airt_goal=self.airt_goal,
|
|
203
|
+
airt_goal_category=self.airt_goal_category,
|
|
204
|
+
**self._study_kwargs(),
|
|
205
|
+
) as span:
|
|
206
|
+
result = await self._execute()
|
|
207
|
+
if hasattr(result, "query_samples"):
|
|
208
|
+
result.query_samples = self._query_samples
|
|
209
|
+
for key, value in self._span_attributes(result).items():
|
|
210
|
+
if value is not None:
|
|
211
|
+
span.set_attribute(key, value)
|
|
212
|
+
span.set_attribute(AIRT_ATTRIBUTE_METRICS_DETAIL, json.dumps(result.metrics_detail))
|
|
213
|
+
return result
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
"""Optional ART (Adversarial Robustness Toolbox) engine for the traditional-ML
|
|
2
|
+
privacy attacks.
|
|
3
|
+
|
|
4
|
+
When ``adversarial-robustness-toolbox`` is installed (the ``airt-ml`` extra), the
|
|
5
|
+
extraction and membership attacks route their core step through ART's reference
|
|
6
|
+
implementations - CopycatCNN / KnockoffNets for extraction, the black-box
|
|
7
|
+
membership inference attacks for membership - instead of the native
|
|
8
|
+
numpy/sklearn engine. Everything here is import-guarded: if ART (or torch) is
|
|
9
|
+
missing, :func:`art_available` returns ``False`` and callers fall back to the
|
|
10
|
+
native engine, so the base SDK never hard-depends on ART.
|
|
11
|
+
|
|
12
|
+
The victim is always wrapped as a black-box: ART only ever sees a
|
|
13
|
+
``predict_fn`` backed by predictions we already collected from the target's API,
|
|
14
|
+
so no extra queries are issued and the attack stays honestly black-box.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
import typing as t
|
|
18
|
+
|
|
19
|
+
import numpy as np
|
|
20
|
+
from loguru import logger
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def art_available() -> bool:
|
|
24
|
+
"""True when the Adversarial Robustness Toolbox and torch import cleanly.
|
|
25
|
+
|
|
26
|
+
We check for ``art.attacks.extraction`` specifically, not just ``import art``:
|
|
27
|
+
the top-level ``art`` name is also owned by the ASCII-art package the SDK
|
|
28
|
+
depends on, so a bare ``import art`` would false-positive on that library.
|
|
29
|
+
ART is not a hard dependency (it collides with the ASCII-art ``art``); this
|
|
30
|
+
returns True only in an environment where the adversarial toolbox is actually
|
|
31
|
+
installed, otherwise the native engine runs.
|
|
32
|
+
"""
|
|
33
|
+
try:
|
|
34
|
+
import torch # noqa: F401
|
|
35
|
+
from art.attacks.extraction import CopycatCNN # noqa: F401
|
|
36
|
+
from art.estimators.classification import BlackBoxClassifier # noqa: F401
|
|
37
|
+
except Exception:
|
|
38
|
+
return False
|
|
39
|
+
return True
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _cached_victim(
|
|
43
|
+
x: np.ndarray,
|
|
44
|
+
proba: np.ndarray,
|
|
45
|
+
nb_classes: int,
|
|
46
|
+
) -> t.Any:
|
|
47
|
+
"""A BlackBoxClassifier whose predict_fn replays already-collected target
|
|
48
|
+
probabilities, keyed by feature-row bytes - ART "queries" it without issuing
|
|
49
|
+
a single extra network call."""
|
|
50
|
+
from art.estimators.classification import BlackBoxClassifier
|
|
51
|
+
|
|
52
|
+
lookup = {row.tobytes(): proba[i] for i, row in enumerate(np.ascontiguousarray(x))}
|
|
53
|
+
uniform = np.full(nb_classes, 1.0 / nb_classes)
|
|
54
|
+
|
|
55
|
+
def predict_fn(batch: np.ndarray) -> np.ndarray:
|
|
56
|
+
rows = np.ascontiguousarray(batch, dtype=x.dtype)
|
|
57
|
+
return np.asarray([lookup.get(r.tobytes(), uniform) for r in rows])
|
|
58
|
+
|
|
59
|
+
return BlackBoxClassifier(
|
|
60
|
+
predict_fn=predict_fn,
|
|
61
|
+
input_shape=(x.shape[1],),
|
|
62
|
+
nb_classes=nb_classes,
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def _torch_thieved(n_features: int, nb_classes: int) -> t.Any:
|
|
67
|
+
"""A small torch MLP wrapped as an ART PyTorchClassifier - the surrogate that
|
|
68
|
+
ART trains to replicate the victim."""
|
|
69
|
+
import torch
|
|
70
|
+
from art.estimators.classification import PyTorchClassifier
|
|
71
|
+
from torch import nn
|
|
72
|
+
|
|
73
|
+
torch.manual_seed(0)
|
|
74
|
+
model = nn.Sequential(
|
|
75
|
+
nn.Linear(n_features, 128),
|
|
76
|
+
nn.ReLU(),
|
|
77
|
+
nn.Linear(128, 64),
|
|
78
|
+
nn.ReLU(),
|
|
79
|
+
nn.Linear(64, nb_classes),
|
|
80
|
+
)
|
|
81
|
+
return PyTorchClassifier(
|
|
82
|
+
model=model,
|
|
83
|
+
loss=nn.CrossEntropyLoss(),
|
|
84
|
+
optimizer=torch.optim.Adam(model.parameters(), lr=1e-3),
|
|
85
|
+
input_shape=(n_features,),
|
|
86
|
+
nb_classes=nb_classes,
|
|
87
|
+
clip_values=(-1e9, 1e9),
|
|
88
|
+
device_type="cpu",
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def art_extract_surrogate(
|
|
93
|
+
strategy: str,
|
|
94
|
+
x: np.ndarray,
|
|
95
|
+
proba: np.ndarray,
|
|
96
|
+
nb_classes: int,
|
|
97
|
+
*,
|
|
98
|
+
nb_epochs: int = 30,
|
|
99
|
+
) -> t.Any | None:
|
|
100
|
+
"""Train a thieved classifier with ART's CopycatCNN (copycat) or KnockoffNets
|
|
101
|
+
(knockoff) against a cached black-box victim.
|
|
102
|
+
|
|
103
|
+
Returns the trained ART classifier (its ``.predict`` yields probabilities), or
|
|
104
|
+
``None`` if ART is unavailable or the run fails - the caller then falls back to
|
|
105
|
+
the native surrogate. Only ``copycat`` and ``knockoff`` map onto ART; the other
|
|
106
|
+
strategies stay native.
|
|
107
|
+
"""
|
|
108
|
+
if strategy not in ("copycat", "knockoff") or not art_available():
|
|
109
|
+
return None
|
|
110
|
+
try:
|
|
111
|
+
from art.attacks.extraction import CopycatCNN, KnockoffNets
|
|
112
|
+
|
|
113
|
+
x = np.ascontiguousarray(x, dtype=np.float32)
|
|
114
|
+
victim = _cached_victim(x, proba, nb_classes)
|
|
115
|
+
thieved = _torch_thieved(x.shape[1], nb_classes)
|
|
116
|
+
n = len(x)
|
|
117
|
+
if strategy == "copycat":
|
|
118
|
+
attack: t.Any = CopycatCNN(
|
|
119
|
+
classifier=victim,
|
|
120
|
+
batch_size_fit=32,
|
|
121
|
+
batch_size_query=32,
|
|
122
|
+
nb_epochs=nb_epochs,
|
|
123
|
+
nb_stolen=n,
|
|
124
|
+
use_probability=False,
|
|
125
|
+
)
|
|
126
|
+
else: # knockoff - soft-label transfer set
|
|
127
|
+
attack = KnockoffNets(
|
|
128
|
+
classifier=victim,
|
|
129
|
+
batch_size_fit=32,
|
|
130
|
+
batch_size_query=32,
|
|
131
|
+
nb_epochs=nb_epochs,
|
|
132
|
+
nb_stolen=n,
|
|
133
|
+
sampling_strategy="random",
|
|
134
|
+
reward="all",
|
|
135
|
+
verbose=False,
|
|
136
|
+
use_probability=True,
|
|
137
|
+
)
|
|
138
|
+
stolen = attack.extract(x=x, thieved_classifier=thieved)
|
|
139
|
+
except Exception as e: # pragma: no cover - defensive fallback
|
|
140
|
+
logger.warning("ART extraction ({}) failed, falling back to native: {}", strategy, e)
|
|
141
|
+
return None
|
|
142
|
+
else:
|
|
143
|
+
logger.debug("ART {} extraction trained thieved classifier on {} samples", strategy, n)
|
|
144
|
+
return stolen
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def art_membership_scores(
|
|
148
|
+
method: str,
|
|
149
|
+
members_x: np.ndarray,
|
|
150
|
+
nonmembers_x: np.ndarray,
|
|
151
|
+
member_proba: np.ndarray,
|
|
152
|
+
nonmember_proba: np.ndarray,
|
|
153
|
+
member_labels: np.ndarray,
|
|
154
|
+
nonmember_labels: np.ndarray,
|
|
155
|
+
nb_classes: int,
|
|
156
|
+
) -> np.ndarray | None:
|
|
157
|
+
"""Per-record membership scores via ART's black-box rule-based membership
|
|
158
|
+
inference (Yeom et al.). Returns an array aligned to
|
|
159
|
+
``[members..., nonmembers...]`` in ``[0, 1]``, or ``None`` to fall back to
|
|
160
|
+
native. Only the ``threshold`` method maps onto ART's black-box rule-based
|
|
161
|
+
attack; ``label_only`` stays native.
|
|
162
|
+
"""
|
|
163
|
+
if method != "threshold" or not art_available():
|
|
164
|
+
return None
|
|
165
|
+
try:
|
|
166
|
+
from art.attacks.inference.membership_inference import (
|
|
167
|
+
MembershipInferenceBlackBoxRuleBased,
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
x = np.ascontiguousarray(np.vstack([members_x, nonmembers_x]), dtype=np.float32)
|
|
171
|
+
proba = np.vstack([member_proba, nonmember_proba])
|
|
172
|
+
labels = np.concatenate([member_labels, nonmember_labels]).astype(int)
|
|
173
|
+
victim = _cached_victim(x, proba, nb_classes)
|
|
174
|
+
attack = MembershipInferenceBlackBoxRuleBased(classifier=victim)
|
|
175
|
+
scores = np.asarray(attack.infer(x, labels, probabilities=True), dtype=np.float64)
|
|
176
|
+
# infer(probabilities=True) returns (N, 2) = [P(non-member), P(member)];
|
|
177
|
+
# the member column is the per-record membership score.
|
|
178
|
+
if scores.ndim == 2 and scores.shape[1] == 2:
|
|
179
|
+
scores = scores[:, 1]
|
|
180
|
+
return scores.ravel()
|
|
181
|
+
except Exception as e: # pragma: no cover - defensive fallback
|
|
182
|
+
logger.warning("ART membership (threshold) failed, falling back to native: {}", e)
|
|
183
|
+
return None
|
|
@@ -181,6 +181,12 @@ class Assessment:
|
|
|
181
181
|
async def __aenter__(self) -> Assessment:
|
|
182
182
|
self._context_token = _current_assessment.set(self)
|
|
183
183
|
self._tracing_enabled = True
|
|
184
|
+
# Register on enter so the assessment id is available to any attack run
|
|
185
|
+
# inside the block - including the traditional-ML privacy attacks that
|
|
186
|
+
# call their own .run() (not assessment.run()). study_span picks up the
|
|
187
|
+
# active assessment via the _current_assessment ContextVar, so the user
|
|
188
|
+
# never has to call register()/complete() or pass airt_assessment_id.
|
|
189
|
+
await self._ensure_started()
|
|
184
190
|
return self
|
|
185
191
|
|
|
186
192
|
async def __aexit__(
|
|
@@ -296,7 +302,11 @@ class Assessment:
|
|
|
296
302
|
|
|
297
303
|
async def _finalize(self) -> None:
|
|
298
304
|
"""Flush pending OTEL spans and mark complete."""
|
|
299
|
-
|
|
305
|
+
# Complete when there is something to finalize: the generative path
|
|
306
|
+
# populates _attack_results, while the privacy attacks emit study spans
|
|
307
|
+
# under a registered assessment (id set on __aenter__). Skip only when
|
|
308
|
+
# both are absent (offline / never used).
|
|
309
|
+
if not self._attack_results and self._assessment_id is None:
|
|
300
310
|
return
|
|
301
311
|
|
|
302
312
|
# Flush pending OTEL spans BEFORE marking complete so CH has data
|
|
@@ -15,6 +15,7 @@ from dreadnode.core.meta import TrialCandidate
|
|
|
15
15
|
from dreadnode.core.scorer import Scorer
|
|
16
16
|
from dreadnode.core.transforms import Transform, TransformsLike
|
|
17
17
|
from dreadnode.generators.generator import Generator, get_generator
|
|
18
|
+
from dreadnode.generators.proxy import resolve_dn_model_to_generator
|
|
18
19
|
from dreadnode.optimization import Study
|
|
19
20
|
from dreadnode.optimization.stopping import score_value
|
|
20
21
|
from dreadnode.samplers import iterative_sampler
|
|
@@ -122,12 +123,15 @@ def crescendo_attack(
|
|
|
122
123
|
# Replace {goal} placeholder in the template
|
|
123
124
|
system_prompt_template = variant_system_prompt.format(goal=goal)
|
|
124
125
|
|
|
125
|
-
# Resolve generator once for reuse across turns
|
|
126
|
+
# Resolve generator once for reuse across turns. `dn/*` ids route through the
|
|
127
|
+
# platform gateway (get_generator can't resolve them); non-dn strings pass
|
|
128
|
+
# through unchanged.
|
|
129
|
+
resolved_attacker = resolve_dn_model_to_generator(attacker_model)
|
|
126
130
|
attacker_generator: Generator
|
|
127
|
-
if isinstance(
|
|
128
|
-
attacker_generator =
|
|
131
|
+
if isinstance(resolved_attacker, Generator):
|
|
132
|
+
attacker_generator = resolved_attacker
|
|
129
133
|
else:
|
|
130
|
-
attacker_generator = get_generator(
|
|
134
|
+
attacker_generator = get_generator(resolved_attacker)
|
|
131
135
|
|
|
132
136
|
# Create the refiner that generates the next prompt in the conversation
|
|
133
137
|
async def crescendo_refiner(trials: "list[Trial[str]]") -> str:
|