dreadnode 2.0.34__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.34 → dreadnode-2.0.36}/PKG-INFO +8 -5
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/agents/agent.py +35 -1
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/__init__.py +79 -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.34 → dreadnode-2.0.36}/dreadnode/airt/assessment.py +11 -1
- dreadnode-2.0.36/dreadnode/airt/atlas/__init__.py +352 -0
- dreadnode-2.0.36/dreadnode/airt/atlas/defense.py +260 -0
- dreadnode-2.0.36/dreadnode/airt/atlas/failure.py +347 -0
- dreadnode-2.0.36/dreadnode/airt/atlas/gate.py +245 -0
- dreadnode-2.0.36/dreadnode/airt/atlas/memory.py +144 -0
- dreadnode-2.0.36/dreadnode/airt/atlas/modes.py +109 -0
- dreadnode-2.0.36/dreadnode/airt/atlas/probes.py +154 -0
- dreadnode-2.0.36/dreadnode/airt/atlas/recon.py +238 -0
- dreadnode-2.0.36/dreadnode/airt/atlas/router.py +199 -0
- dreadnode-2.0.36/dreadnode/airt/atlas/strategy.py +875 -0
- {dreadnode-2.0.34 → 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.36/dreadnode/airt/target.py +193 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/targets/__init__.py +12 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/targets/http.py +9 -4
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/targets/message.py +14 -0
- dreadnode-2.0.36/dreadnode/airt/targets/prediction.py +211 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/targets/spec.py +9 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/targets/streaming/nova_sonic.py +9 -5
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/api/models.py +24 -1
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/cli/airt.py +291 -5
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/cli/args.py +8 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/cli/capability.py +18 -5
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/cli/evaluation.py +91 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/cli/main.py +2 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/client/managed_client.py +2 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/client/models.py +2 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/client/runtime_client.py +63 -9
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/main.py +18 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/print_mode.py +7 -1
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/server/app.py +147 -11
- dreadnode-2.0.36/dreadnode/app/server/auth.py +120 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/server/capability_manager.py +50 -1
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/server/runtime_events.py +7 -1
- dreadnode-2.0.36/dreadnode/app/server/runtime_token.py +395 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/server/session_hydrator.py +44 -0
- {dreadnode-2.0.34 → 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.34 → dreadnode-2.0.36}/dreadnode/app/tui/app.py +87 -2
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/screens/capabilities.py +15 -2
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/screens/models.py +5 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/screens/sessions.py +4 -4
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/sessions_manager.py +97 -5
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/turn_coordinator.py +14 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/conversation.py +38 -1
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/tool.py +21 -3
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/agent-output.md +5 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/dependencies-and-checks.md +3 -3
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/hooks.md +20 -1
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/policies.md +21 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/tools.md +21 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/sdk/capabilities.md +1 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/tui/default-tools.md +11 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/airt.md +26 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/evaluation.md +5 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/credits.md +1 -1
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/capabilities/install.py +79 -11
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/capabilities/loader.py +404 -46
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/core/environment.py +10 -1
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/generators/proxy.py +57 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/optimization/study.py +75 -6
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/scorers/judge.py +15 -4
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/tracing/constants.py +32 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/transforms/audio.py +4 -4
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/transforms/language.py +18 -9
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/transforms/refine.py +9 -4
- {dreadnode-2.0.34 → dreadnode-2.0.36}/pyproject.toml +38 -10
- dreadnode-2.0.34/dreadnode/app/server/auth.py +0 -66
- dreadnode-2.0.34/dreadnode/app/server/ws_auth.py +0 -76
- {dreadnode-2.0.34 → dreadnode-2.0.36}/.gitignore +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/LICENSE +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/README.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/__main__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/agents/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/agents/engines/AGENTS.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/agents/engines/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/agents/engines/base.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/agents/engines/claude_code.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/agents/engines/native.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/agents/events.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/agents/exceptions.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/agents/format.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/agents/hooks.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/agents/judge.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/agents/mcp/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/agents/mcp/auth.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/agents/mcp/client.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/agents/mcp/config.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/agents/mcp/server.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/agents/process_judge.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/agents/reactions.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/agents/sanitize.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/agents/skills.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/agents/stopping.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/agents/subagent.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/agents/tool_resolution.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/agents/tools.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/agents/trajectory.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/adversarial_reasoning.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/advpromptier.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/alignment_faking.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/analogy_escalation.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/analytics/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/analytics/aggregator.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/analytics/classifier.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/analytics/compliance.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/analytics/engine.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/analytics/recommendations.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/analytics/types.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/aprt_progressive.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/attention_shifting.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/autodan_turbo.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/autoredteamer.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/beast.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/compliance/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/compliance/atlas.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/compliance/nist.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/compliance/owasp.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/compliance/owasp_agentic.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/compliance/saif.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/constants.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/cot_jailbreak.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/data/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/data/assets/audio/adversarial_query.mp3 +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/data/assets/image/bomb.jpg +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/data/assets/image/meth.png +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/data/prompts/adversarial_benchmark_subset.csv +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/data/prompts/ai_safety.csv +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/data/rubrics/data_exfiltration.yaml +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/data/rubrics/goal_hijacking.yaml +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/data/rubrics/idor.yaml +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/data/rubrics/memory_poisoning.yaml +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/data/rubrics/privilege_escalation.yaml +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/data/rubrics/rce.yaml +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/data/rubrics/scope_creep.yaml +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/data/rubrics/tool_chaining.yaml +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/data/rubrics/tool_selection_safety.yaml +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/data/rubrics/unbounded_agency.yaml +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/data/rubrics/web_chatbot_security.yaml +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/data/templates/crescendo/variant_1.yaml +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/data/templates/crescendo/variant_2.yaml +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/data/templates/crescendo/variant_3.yaml +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/data/templates/crescendo/variant_4.yaml +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/data/templates/crescendo/variant_5.yaml +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/deep_inception.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/drattack.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/echo_chamber.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/events.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/genetic_persona.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/goat.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/goat_v2.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/gptfuzzer.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/humor_bypass.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/image.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/j2_meta.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/jbdistill.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/jbfuzz.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/lrm_autonomous.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/mapf.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/message_parts.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/multimodal.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/nexus.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/pair.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/persona_hijack.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/prompt.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/quantization_safety.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/rainbow.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/refusal_aware.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/renellm.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/reporting/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/reporting/json_report.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/reporting/llm_summary.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/reporting/markdown.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/reward_hacking.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/salami_slicing.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/self_persuasion.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/siren.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/tap.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/targets/auth.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/targets/factory.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/targets/streaming/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/templatefuzz.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/tmap_trajectory.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/trojail.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/airt/watermark_removal.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/api/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/api/client.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/cli/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/cli/dataset.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/cli/environment.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/cli/inference_model.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/cli/judge.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/cli/model.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/cli/optimize.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/cli/runtime.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/cli/sandbox.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/cli/secret.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/cli/session.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/cli/shared.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/cli/task.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/cli/task_set.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/cli/templates/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/cli/templates/init/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/cli/templates/init/challenge/Dockerfile +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/cli/templates/init/docker-compose.yaml +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/cli/templates/init/provision.sh +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/cli/templates/init/solution.sh +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/cli/templates/init/task-remote.yaml.tmpl +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/cli/templates/init/task.yaml.tmpl +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/cli/templates/init/teardown.sh +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/cli/templates/init/verify.sh +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/cli/train.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/cli/worlds.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/client/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/client/interactive.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/client/transports.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/config.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/env.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/model_catalog.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/paths.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/server/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/server/model_resolution.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/server/prompt.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/server/prompt_registry.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/server/session_persistence.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/server/turn_coordinator.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/server/utils.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/server/worker_manager.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/auth_flow.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/capabilities_manager.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/command_dispatcher.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/commands.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/connection.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/dreadnode.tcss +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/error_handler.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/model_manager.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/model_variants.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/profile_manager.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/runtime_cache.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/screen_router.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/screens/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/screens/auth.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/screens/base.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/screens/capability_docs.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/screens/connection_error.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/screens/console.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/screens/environments.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/screens/evaluations.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/screens/raw_spans.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/screens/readme.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/screens/runtimes.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/screens/sandboxes.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/screens/secrets.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/screens/services.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/screens/theme_showcase.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/screens/traces.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/screens/workspaces.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/spans_reader.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/status_messages.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/theme.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/tool_format.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/turn_lifecycle.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/turn_reducer.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/turn_state_phase.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/update_check.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/agent_dialog.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/agent_suggester.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/composer.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/confirm_modal.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/context_bar.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/flash.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/header_bar.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/help_panel.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/human_prompt.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/mention_overlay.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/message_queue.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/new_messages_pill.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/overlay_mixin.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/permission_prompt.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/profile_dialog.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/prompt_info.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/rewind_picker.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/session_sidebar.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/skills_dialog.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/slash_overlay.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/status_bar.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/throbber.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/tool_progress.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/tools_dialog.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/welcome.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/widgets/whoami.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/app/tui/wire_events.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/MAINTAINING.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/agents/dreadnode.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/capability.yaml +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/SKILL.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/capability-improvement.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/methodology-grounding.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/prior-art-audit.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/promoting-capabilities.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/quality-bar.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/INDEX.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/agents.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/custom-engines.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/engines.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/env-vars.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/events.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/flags.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/installing.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/manifest.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/mcp-servers.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/overview.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/publishing.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/quickstart.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/skills.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/workers-reference.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/workers.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/capabilities/writing-skills.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references/sdk/agents.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/references-and-depth.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/creating-capabilities/runtime-default-capability.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/SKILL.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/INDEX.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/capability.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/dataset.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/env.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/inference-model.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/main.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/model.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/optimize.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/overview.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/runtime.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/sandbox.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/secret.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/task-set.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/task.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/train.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/cli/worlds.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-cli/references/getting-started/authentication.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/SKILL.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/INDEX.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/capabilities/installing.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/capabilities/overview.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/getting-started/authentication.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/getting-started/overview.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/getting-started/quickstart.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/chat-models.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/organizations.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/overview.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/projects.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/secrets.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/settings.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/platform/workspaces.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/runtimes/configuration.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/runtimes/managing.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/runtimes/manifest-reference.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/runtimes/overview.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/runtimes/quickstart.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/runtimes/serve.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/sandboxes/environment-lifecycle.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/sandboxes/inspecting.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/sandboxes/overview.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/dreadnode-concepts/references/sandboxes/runtime-limits.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/getting-started/SKILL.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/dreadnode/skills/research-capabilities/SKILL.md +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/self-improvement/.gitignore +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/self-improvement/capability.yaml +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/self-improvement/hooks/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/self-improvement/hooks/observer.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/self-improvement/self_improvement_lib/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/self-improvement/self_improvement_lib/classifier.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/self-improvement/self_improvement_lib/reflector_goal.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/self-improvement/self_improvement_lib/skill_io.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/self-improvement/skills-promoted/.gitkeep +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/self-improvement/skills-proposed/.gitkeep +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/self-improvement/tools/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/self-improvement/tools/reflector.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/builtin_capabilities/self-improvement/tools/skill_stats.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/capabilities/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/capabilities/capability.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/capabilities/flags.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/capabilities/sync.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/capabilities/tool_rules.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/capabilities/types.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/capabilities/worker.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/capabilities/worker_runner.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/core/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/core/conditions.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/core/discovery.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/core/exceptions.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/core/execution.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/core/hook.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/core/judge.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/core/load.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/core/log.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/core/meta/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/core/meta/config.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/core/meta/context.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/core/meta/hydrate.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/core/meta/introspect.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/core/metric.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/core/object.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/core/scorer.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/core/serialization.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/core/stopping.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/core/task.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/core/templating.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/core/transforms.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/core/types/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/core/types/audio.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/core/types/base.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/core/types/common.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/core/types/image.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/core/types/object_3d.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/core/types/table.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/core/types/text.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/core/types/video.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/core/util.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/datasets/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/datasets/dataset.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/datasets/hf.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/datasets/local.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/evaluations/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/evaluations/console.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/evaluations/evaluation.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/evaluations/events.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/evaluations/format.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/evaluations/result.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/evaluations/sample.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/generators/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/generators/caching.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/generators/chat.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/generators/data.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/generators/exceptions.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/generators/generator/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/generators/generator/base.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/generators/generator/http.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/generators/generator/litellm_.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/generators/generator/transformers_.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/generators/generator/vllm_.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/generators/message.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/generators/models.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/generators/parsing.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/generators/tokenizer/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/generators/tokenizer/base.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/generators/tokenizer/transformers_.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/generators/utils.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/items/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/items/config.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/items/models.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/judges/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/judges/outcome.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/judges/trajectory.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/judges/trajectory_tools.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/models/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/models/hf.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/models/local.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/models/model.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/optimization/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/optimization/adapters/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/optimization/adapters/_env_eval.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/optimization/adapters/agent.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/optimization/adapters/env.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/optimization/adapters/runtime.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/optimization/adapters/stack.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/optimization/api.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/optimization/backends/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/optimization/backends/base.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/optimization/backends/gepa.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/optimization/collectors.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/optimization/config.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/optimization/console.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/optimization/events.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/optimization/format.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/optimization/jobs.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/optimization/result.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/optimization/sampler.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/optimization/sampling.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/optimization/search.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/optimization/stopping.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/optimization/trial.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/packaging/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/packaging/loader.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/packaging/manifest.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/packaging/oci.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/packaging/package.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/packaging/task_validation.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/policies/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/policies/guard.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/policies/reconciliation.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/policies/rubrics/process/default.yaml +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/py.typed +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/samplers/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/samplers/boundary.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/samplers/fuzzing.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/samplers/graph.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/samplers/grid.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/samplers/image.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/samplers/mapelites.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/samplers/optuna.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/samplers/random.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/samplers/registry.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/samplers/strategy.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/scorers/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/scorers/advanced_jailbreak_detection.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/scorers/agent_security.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/scorers/agentic.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/scorers/agentic_workflow.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/scorers/attack_outcome.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/scorers/classification.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/scorers/consistency.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/scorers/contains.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/scorers/cosine_sim.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/scorers/credentials.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/scorers/crucible.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/scorers/documentation_security.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/scorers/exfiltration_detection.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/scorers/format.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/scorers/harm.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/scorers/ide_security.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/scorers/image.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/scorers/json.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/scorers/judge_ensemble.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/scorers/length.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/scorers/lexical.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/scorers/mcp_security.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/scorers/memorization.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/scorers/multi_agent_security.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/scorers/pii.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/scorers/prompt_leak.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/scorers/readability.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/scorers/reasoning_security.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/scorers/sentiment.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/scorers/similarity.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/scorers/structural_detection.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/scorers/supply_chain_detection.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/storage/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/storage/providers.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/storage/session_store.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/storage/storage.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/tools/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/tools/_ripgrep.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/tools/apply_patch.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/tools/dreadnode_cli.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/tools/editing.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/tools/execute.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/tools/fetch.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/tools/glob.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/tools/grep.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/tools/interaction.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/tools/ls.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/tools/memory.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/tools/project_memory.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/tools/read.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/tools/report.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/tools/report_items.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/tools/task.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/tools/think.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/tools/todo.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/tools/trajectory_search.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/tools/web_extract.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/tools/web_search.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/tools/write.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/tracing/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/tracing/convert.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/tracing/exporter.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/tracing/exporters.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/tracing/span.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/tracing/spans.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/tracing/trace_converter.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/_progress.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/base.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/dpo.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/env_rollouts.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/etl/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/etl/_common.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/etl/rl.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/etl/sft.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/etl/worlds.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/events.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/grpo.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/jobs.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/models.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/ppo.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/prime.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/ray/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/ray/async_trainer.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/ray/config.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/ray/coordinator.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/ray/distributed.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/ray/dpo.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/ray/experience.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/ray/fsdp2_learner.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/ray/inference.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/ray/learner.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/ray/multi_turn.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/ray/ppo.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/ray/reward_model.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/ray/rollout_env.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/ray/rollout_worker.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/ray/sft.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/ray/trainer.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/recipes.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/rewards/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/rewards/aggregator.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/rewards/functions.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/rewards/scorer_bridge.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/rewards/shaping.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/rewards/types.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/rollouts/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/rollouts/adapters.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/rollouts/agent_rollout.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/rollouts/orchestrator.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/rollouts/types.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/rollouts/worlds.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/serving/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/serving/vllm_client.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/sft.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/tinker/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/tinker/config.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/tinker/data.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/tinker/renderer.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/tinker/rl.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/tinker/trainer.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/tinker_sft.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/training/utils.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/transforms/__init__.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/transforms/advanced_jailbreak.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/transforms/adversarial_suffix.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/transforms/agent_skill.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/transforms/agentic_workflow.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/transforms/backdoor_finetune.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/transforms/browser_agent_attacks.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/transforms/cipher.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/transforms/competitive_parity.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/transforms/constitutional.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/transforms/document.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/transforms/documentation_poison.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/transforms/encoding.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/transforms/exfiltration.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/transforms/flip_attack.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/transforms/guardrail_bypass.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/transforms/ide_injection.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/transforms/image.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/transforms/injection.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/transforms/json_tools.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/transforms/logic_bomb.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/transforms/mcp_attacks.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/transforms/multi_agent_attacks.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/transforms/multimodal_attacks.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/transforms/persuasion.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/transforms/perturbation.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/transforms/pii_extraction.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/transforms/pythonic_tools.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/transforms/rag_poisoning.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/transforms/reasoning_attacks.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/transforms/response_steering.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/transforms/structural_exploits.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/transforms/stylistic.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/transforms/substitution.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/transforms/supply_chain.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/transforms/swap.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/transforms/system_prompt_extraction.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/transforms/text.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/transforms/video.py +0 -0
- {dreadnode-2.0.34 → dreadnode-2.0.36}/dreadnode/transforms/xml_tools.py +0 -0
- {dreadnode-2.0.34 → 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
|
|
@@ -9,6 +9,9 @@ License-File: LICENSE
|
|
|
9
9
|
Requires-Python: <3.14,>=3.11
|
|
10
10
|
Requires-Dist: aiofiles<25.0.0,>=24.1.0
|
|
11
11
|
Requires-Dist: art<7.0.0,>=6.5
|
|
12
|
+
Requires-Dist: aws-sdk-bedrock-runtime>=0.7.0; python_version >= '3.12'
|
|
13
|
+
Requires-Dist: awscrt>=0.27.0; python_version >= '3.12'
|
|
14
|
+
Requires-Dist: boto3>=1.40.0
|
|
12
15
|
Requires-Dist: coolname<3.0.0,>=2.2.0
|
|
13
16
|
Requires-Dist: croniter<7.0.0,>=6.0.0
|
|
14
17
|
Requires-Dist: cyclopts>=4.2.0
|
|
@@ -40,6 +43,7 @@ Requires-Dist: pydantic-xml>=2.14.0
|
|
|
40
43
|
Requires-Dist: pydantic<3.0.0,>=2.9.2
|
|
41
44
|
Requires-Dist: pyyaml>=6.0.2
|
|
42
45
|
Requires-Dist: scipy<2.0.0,>=1.11.0
|
|
46
|
+
Requires-Dist: smithy-aws-core>=0.7.0; python_version >= '3.12'
|
|
43
47
|
Requires-Dist: soundfile<1.0.0,>=0.13.1
|
|
44
48
|
Requires-Dist: starlette<1.4.0,>=1.3.1
|
|
45
49
|
Requires-Dist: textual>=8.0.2
|
|
@@ -47,6 +51,9 @@ Requires-Dist: transformers>=4.57.1
|
|
|
47
51
|
Requires-Dist: uvicorn>=0.34.0
|
|
48
52
|
Requires-Dist: websockets>=14.0
|
|
49
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'
|
|
50
57
|
Provides-Extra: all
|
|
51
58
|
Requires-Dist: confusables<2.0.0,>=1.2.0; extra == 'all'
|
|
52
59
|
Requires-Dist: moviepy<3.0.0,>=2.1.2; extra == 'all'
|
|
@@ -63,10 +70,6 @@ Requires-Dist: torch>=2.9.0; extra == 'all'
|
|
|
63
70
|
Provides-Extra: claude-code
|
|
64
71
|
Requires-Dist: claude-agent-sdk>=0.1.0; extra == 'claude-code'
|
|
65
72
|
Provides-Extra: nova-sonic
|
|
66
|
-
Requires-Dist: aws-sdk-bedrock-runtime>=0.7.0; (python_version >= '3.12') and extra == 'nova-sonic'
|
|
67
|
-
Requires-Dist: awscrt>=0.27.0; extra == 'nova-sonic'
|
|
68
|
-
Requires-Dist: boto3>=1.40.0; extra == 'nova-sonic'
|
|
69
|
-
Requires-Dist: smithy-aws-core>=0.7.0; (python_version >= '3.12') and extra == 'nova-sonic'
|
|
70
73
|
Provides-Extra: scoring
|
|
71
74
|
Requires-Dist: confusables<2.0.0,>=1.2.0; extra == 'scoring'
|
|
72
75
|
Requires-Dist: nltk<4.0.0,>=3.9.1; extra == 'scoring'
|
|
@@ -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
|
|
@@ -62,6 +72,7 @@ from dreadnode.airt.alignment_faking import alignment_faking_attack
|
|
|
62
72
|
from dreadnode.airt.analogy_escalation import analogy_escalation_attack
|
|
63
73
|
from dreadnode.airt.aprt_progressive import aprt_progressive_attack
|
|
64
74
|
from dreadnode.airt.assessment import Assessment
|
|
75
|
+
from dreadnode.airt.atlas import atlas_attack
|
|
65
76
|
from dreadnode.airt.attention_shifting import attention_shifting_attack
|
|
66
77
|
from dreadnode.airt.autodan_turbo import autodan_turbo_attack
|
|
67
78
|
from dreadnode.airt.autoredteamer import autoredteamer_attack
|
|
@@ -71,6 +82,27 @@ from dreadnode.airt.crescendo import crescendo_attack
|
|
|
71
82
|
from dreadnode.airt.deep_inception import deep_inception_attack
|
|
72
83
|
from dreadnode.airt.drattack import drattack
|
|
73
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
|
+
)
|
|
74
106
|
from dreadnode.airt.genetic_persona import genetic_persona_attack
|
|
75
107
|
from dreadnode.airt.goat import goat_attack
|
|
76
108
|
from dreadnode.airt.goat_v2 import goat_v2_attack
|
|
@@ -82,11 +114,23 @@ from dreadnode.airt.image import (
|
|
|
82
114
|
simba_attack,
|
|
83
115
|
zoo_attack,
|
|
84
116
|
)
|
|
117
|
+
from dreadnode.airt.inversion import (
|
|
118
|
+
confidence_inversion,
|
|
119
|
+
nes_inversion,
|
|
120
|
+
)
|
|
85
121
|
from dreadnode.airt.j2_meta import j2_meta_attack
|
|
86
122
|
from dreadnode.airt.jbdistill import jbdistill_attack
|
|
87
123
|
from dreadnode.airt.jbfuzz import jbfuzz_attack
|
|
88
124
|
from dreadnode.airt.lrm_autonomous import lrm_autonomous_attack
|
|
89
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
|
+
)
|
|
90
134
|
from dreadnode.airt.multimodal import multimodal_attack
|
|
91
135
|
from dreadnode.airt.nexus import nexus_attack
|
|
92
136
|
from dreadnode.airt.pair import pair_attack
|
|
@@ -101,9 +145,13 @@ from dreadnode.airt.salami_slicing import salami_slicing_attack
|
|
|
101
145
|
from dreadnode.airt.self_persuasion import self_persuasion_attack
|
|
102
146
|
from dreadnode.airt.siren import siren_attack
|
|
103
147
|
from dreadnode.airt.tap import tap_attack
|
|
148
|
+
from dreadnode.airt.target import extract_response_text, extract_tool_calls
|
|
104
149
|
from dreadnode.airt.targets import (
|
|
150
|
+
Prediction,
|
|
151
|
+
PredictionTargetSpec,
|
|
105
152
|
TargetAuth,
|
|
106
153
|
TargetSpec,
|
|
154
|
+
build_prediction_target,
|
|
107
155
|
build_target,
|
|
108
156
|
nova_sonic_target,
|
|
109
157
|
)
|
|
@@ -114,41 +162,64 @@ from dreadnode.airt.watermark_removal import watermark_removal_attack
|
|
|
114
162
|
|
|
115
163
|
__all__ = [
|
|
116
164
|
"Assessment",
|
|
165
|
+
"Prediction",
|
|
166
|
+
"PredictionTargetSpec",
|
|
117
167
|
"TargetAuth",
|
|
118
168
|
"TargetSpec",
|
|
169
|
+
"activethief_extraction",
|
|
119
170
|
"adversarial_reasoning_attack",
|
|
120
171
|
"advpromptier_attack",
|
|
121
172
|
"alignment_faking_attack",
|
|
122
173
|
"analogy_escalation_attack",
|
|
123
174
|
"aprt_progressive_attack",
|
|
175
|
+
"atlas_attack",
|
|
124
176
|
"attention_shifting_attack",
|
|
125
177
|
"autodan_turbo_attack",
|
|
126
178
|
"autoredteamer_attack",
|
|
179
|
+
"bae_evasion",
|
|
127
180
|
"beast_attack",
|
|
181
|
+
"boundary_evasion",
|
|
182
|
+
"build_prediction_target",
|
|
128
183
|
"build_target",
|
|
184
|
+
"confidence_inversion",
|
|
185
|
+
"copycat_extraction",
|
|
129
186
|
"cot_jailbreak_attack",
|
|
130
187
|
"crescendo_attack",
|
|
131
188
|
"deep_inception_attack",
|
|
189
|
+
"deepwordbug_evasion",
|
|
190
|
+
"distillation_extraction",
|
|
132
191
|
"drattack",
|
|
133
192
|
"echo_chamber_attack",
|
|
193
|
+
"entropy_membership",
|
|
194
|
+
"equation_solving_extraction",
|
|
195
|
+
"extract_response_text",
|
|
196
|
+
"extract_tool_calls",
|
|
134
197
|
"genetic_persona_attack",
|
|
135
198
|
"goat_attack",
|
|
136
199
|
"goat_v2_attack",
|
|
137
200
|
"gptfuzzer_attack",
|
|
138
201
|
"hopskipjump_attack",
|
|
202
|
+
"hopskipjump_evasion",
|
|
139
203
|
"humor_bypass_attack",
|
|
140
204
|
"j2_meta_attack",
|
|
205
|
+
"jacobian_extraction",
|
|
141
206
|
"jbdistill_attack",
|
|
142
207
|
"jbfuzz_attack",
|
|
208
|
+
"knockoff_extraction",
|
|
209
|
+
"label_only_membership",
|
|
210
|
+
"lira_membership",
|
|
211
|
+
"loss_membership",
|
|
143
212
|
"lrm_autonomous_attack",
|
|
144
213
|
"mapf_attack",
|
|
145
214
|
"multimodal_attack",
|
|
146
215
|
"nes_attack",
|
|
216
|
+
"nes_inversion",
|
|
147
217
|
"nexus_attack",
|
|
148
218
|
"nova_sonic_target",
|
|
149
219
|
"pair_attack",
|
|
150
220
|
"persona_hijack_attack",
|
|
151
221
|
"prompt_attack",
|
|
222
|
+
"pwws_evasion",
|
|
152
223
|
"quantization_safety_attack",
|
|
153
224
|
"rainbow_attack",
|
|
154
225
|
"refusal_aware_attack",
|
|
@@ -156,12 +227,20 @@ __all__ = [
|
|
|
156
227
|
"reward_hacking_attack",
|
|
157
228
|
"salami_slicing_attack",
|
|
158
229
|
"self_persuasion_attack",
|
|
230
|
+
"shadow_model_membership",
|
|
159
231
|
"simba_attack",
|
|
232
|
+
"simba_evasion",
|
|
160
233
|
"siren_attack",
|
|
234
|
+
"square_evasion",
|
|
161
235
|
"tap_attack",
|
|
162
236
|
"templatefuzz_attack",
|
|
237
|
+
"text_evasion",
|
|
238
|
+
"textbugger_evasion",
|
|
239
|
+
"textfooler_evasion",
|
|
240
|
+
"threshold_membership",
|
|
163
241
|
"tmap_trajectory_attack",
|
|
164
242
|
"trojail_attack",
|
|
165
243
|
"watermark_removal_attack",
|
|
166
244
|
"zoo_attack",
|
|
245
|
+
"zoo_evasion",
|
|
167
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
|