hackagent 0.15.0__tar.gz → 0.16.0__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.
- {hackagent-0.15.0 → hackagent-0.16.0}/.gitignore +5 -0
- hackagent-0.16.0/PKG-INFO +121 -0
- hackagent-0.16.0/README.md +80 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/static/h4rm3l/decorators/base.py +17 -3
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/static/mml/image_encoder.py +35 -17
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/hermes/README.md +7 -5
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/cli/commands/examples.py +48 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/tui/app.py +26 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/tui/views/campaign/form.py +7 -3
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/tui/views/campaign/schema.py +20 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/models/completions/cli.py +12 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/models/completions/codex.py +6 -3
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/models/completions/hermes.py +46 -16
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/orchestrator/campaign/overrides.py +7 -1
- {hackagent-0.15.0 → hackagent-0.16.0}/pyproject.toml +3 -3
- hackagent-0.15.0/PKG-INFO +0 -204
- hackagent-0.15.0/README.md +0 -163
- {hackagent-0.15.0 → hackagent-0.16.0}/LICENSE +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/_version.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/_lib/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/_lib/graphviz.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/_lib/prompt_parser.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/_lib/response.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/_lib/templates.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/_lib/transforms.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/adaptive/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/adaptive/advprefix/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/adaptive/advprefix/attack.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/adaptive/advprefix/config.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/adaptive/advprefix/prompts.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/adaptive/autodan_turbo/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/adaptive/autodan_turbo/attack.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/adaptive/autodan_turbo/config.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/adaptive/autodan_turbo/library.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/adaptive/autodan_turbo/prompts.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/adaptive/bon/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/adaptive/bon/attack.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/adaptive/bon/augment.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/adaptive/bon/config.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/adaptive/pair/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/adaptive/pair/attack.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/adaptive/pair/config.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/adaptive/pair/prompts.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/adaptive/pap/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/adaptive/pap/attack.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/adaptive/pap/config.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/adaptive/pap/taxonomy.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/adaptive/tap/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/adaptive/tap/attack.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/adaptive/tap/config.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/adaptive/tap/prompts.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/contract.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/indirect/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/indirect/rag/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/indirect/rag/attack.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/indirect/rag/config.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/indirect/rag/prompts.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/indirect/rag/retrieval.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/indirect/tool_output_ipi/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/indirect/tool_output_ipi/attack.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/indirect/tool_output_ipi/config.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/indirect/tool_output_ipi/prompts.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/iterative.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/multi_turn/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/multi_turn/crescendo/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/multi_turn/crescendo/attack.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/multi_turn/crescendo/config.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/multi_turn/crescendo/prompts.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/registry.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/static/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/static/base.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/static/baseline/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/static/baseline/attack.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/static/baseline/config.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/static/cipherchat/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/static/cipherchat/attack.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/static/cipherchat/config.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/static/cipherchat/demonstrations.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/static/cipherchat/encodings/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/static/cipherchat/encodings/base.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/static/cipherchat/encodings/byte_escape.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/static/cipherchat/encodings/mapping.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/static/cipherchat/encodings/prompts.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/static/cipherchat/encodings/registry.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/static/fc/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/static/fc/attack.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/static/fc/config.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/static/fc/flowchart_renderer.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/static/fc/prompts.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/static/flipattack/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/static/flipattack/attack.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/static/flipattack/config.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/static/flipattack/prompts.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/static/h4rm3l/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/static/h4rm3l/attack.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/static/h4rm3l/config.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/static/h4rm3l/decorators/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/static/h4rm3l/decorators/compiler.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/static/h4rm3l/decorators/llm.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/static/h4rm3l/decorators/static.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/static/h4rm3l/programs.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/static/mml/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/static/mml/attack.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/static/mml/config.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/static/mml/prompts.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/static/static_template/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/static/static_template/attack.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/static/static_template/config.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/static/static_template/templates.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/trace.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/attacks.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/base.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/craft_adversarial_data/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/craft_adversarial_data/profile.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/craft_adversarial_data/types.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/craft_adversarial_data/vulnerabilities.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/credential_exposure/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/credential_exposure/profile.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/credential_exposure/types.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/credential_exposure/vulnerabilities.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/excessive_agency/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/excessive_agency/profile.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/excessive_agency/types.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/excessive_agency/vulnerabilities.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/input_manipulation_attack/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/input_manipulation_attack/profile.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/input_manipulation_attack/types.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/input_manipulation_attack/vulnerabilities.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/jailbreak/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/jailbreak/profile.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/jailbreak/types.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/jailbreak/vulnerabilities.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/malicious_tool_invocation/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/malicious_tool_invocation/profile.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/malicious_tool_invocation/types.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/malicious_tool_invocation/vulnerabilities.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/misinformation/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/misinformation/profile.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/misinformation/types.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/misinformation/vulnerabilities.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/model_evasion/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/model_evasion/profile.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/model_evasion/types.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/model_evasion/vulnerabilities.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/profile_helpers.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/profile_types.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/prompt_injection/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/prompt_injection/profile.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/prompt_injection/templates.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/prompt_injection/types.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/prompt_injection/vulnerabilities.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/public_facing_application_exploitation/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/public_facing_application_exploitation/profile.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/public_facing_application_exploitation/types.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/public_facing_application_exploitation/vulnerabilities.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/registry.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/sensitive_information_disclosure/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/sensitive_information_disclosure/profile.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/sensitive_information_disclosure/types.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/sensitive_information_disclosure/vulnerabilities.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/system_prompt_leakage/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/system_prompt_leakage/profile.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/system_prompt_leakage/types.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/system_prompt_leakage/vulnerabilities.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/utils.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/vector_embedding_weaknesses_exploit/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/vector_embedding_weaknesses_exploit/profile.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/vector_embedding_weaknesses_exploit/types.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/risks/vector_embedding_weaknesses_exploit/vulnerabilities.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/catalog/taxonomy.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/client.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/core/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/core/async_utils.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/core/contracts/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/core/contracts/_base.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/core/contracts/completion.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/core/contracts/enums.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/core/contracts/judging.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/core/contracts/messages.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/core/contracts/protocols.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/core/contracts/specs.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/core/defaults.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/core/errors.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/core/logging.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/core/settings.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/datasets/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/datasets/base.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/datasets/calibration.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/datasets/config.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/datasets/goals.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/datasets/intents.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/datasets/labelling.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/datasets/omnisafebench/dataset.json +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/datasets/presets.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/datasets/providers/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/datasets/providers/file.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/datasets/providers/huggingface.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/datasets/providers/url_json.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/datasets/registry.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/datasets/taxonomy.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/datasets/taxonomy.yaml +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/evaluation/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/evaluation/audit.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/evaluation/base.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/evaluation/config.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/evaluation/judges.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/evaluation/metrics.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/evaluation/panel.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/evaluation/patterns.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/claude/README.md +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/claude/flipattack-claude.yaml +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/claude/flipattack-ollama.yaml +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/codex/README.md +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/codex/h4rm3l-codex.yaml +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/codex/h4rm3l-ollama.yaml +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/google_adk/jailbreak_eval/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/google_adk/jailbreak_eval/advprefix-adk.yaml +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/google_adk/jailbreak_eval/agent.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/google_adk/multi_tool_agent/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/google_adk/multi_tool_agent/advprefix-multi-tool.yaml +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/google_adk/multi_tool_agent/agent.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/hermes/flipattack-hermes.yaml +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/langchain/rag/README.md +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/langchain/rag/advprefix-corpbot.yaml +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/langchain/rag/agent_client.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/langchain/rag/agent_server.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/langchain/rag/ingest.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/langchain/rag/policies.pdf +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/langchain/rag/read_db.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/litellm_multi_provider/README.md +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/litellm_multi_provider/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/litellm_multi_provider/tap-any-provider.yaml +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/ollama/flipattack-local.yaml +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/ollama/h4rm3l-demo.yaml +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/ollama/risk-evaluation.yaml +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/openai_sdk/db_tool_sandbox/README.md +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/openai_sdk/db_tool_sandbox/agent.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/openai_sdk/db_tool_sandbox/flipattack-sqldesk.yaml +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/openai_sdk/db_tool_sandbox/sandbox.db +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/openai_sdk/multi_judge/README.md +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/openai_sdk/multi_judge/flipattack-multi-judge.yaml +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/openai_sdk/pc_tool_sandbox/README.md +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/openai_sdk/pc_tool_sandbox/agent.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/openai_sdk/pc_tool_sandbox/confidential/db_credentials.txt +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/openai_sdk/pc_tool_sandbox/pair-vaultdesk.yaml +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/openai_sdk/quick_evaluation/README.md +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/openai_sdk/quick_evaluation/h4rm3l-granite.yaml +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/openai_sdk/rag/README.md +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/openai_sdk/rag/agent_server.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/openai_sdk/rag/h4rm3l-corpbot.yaml +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/openai_sdk/rag/ingest.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/openai_sdk/rag/policies.pdf +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/rag/.gitignore +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/rag/indirect-injection.yaml +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/rag/test_data/gender_studies_overview.txt +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/vllm/risk-evaluation.yaml +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/web/README.md +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/web/plan.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/examples/web/tap-site-chatbot.yaml +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/cli/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/cli/banner.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/cli/bootstrap.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/cli/commands/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/cli/commands/campaign.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/cli/commands/config.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/cli/commands/datasets.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/cli/commands/results.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/cli/commands/web.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/cli/config.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/cli/help_page.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/cli/logging_setup.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/cli/main.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/cli/safe_stdio.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/cli/utils.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/tui/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/tui/base.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/tui/events.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/tui/logger.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/tui/theme.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/tui/views/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/tui/views/agents.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/tui/views/audit.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/tui/views/campaign/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/tui/views/campaign/builder.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/tui/views/campaign/draft.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/tui/views/campaign/outline.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/tui/views/campaign/report.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/tui/views/campaign/screens.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/tui/views/campaign/welcome.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/tui/views/config.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/tui/views/results/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/tui/views/results/export.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/tui/views/results/formatters/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/tui/views/results/formatters/datetimes.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/tui/views/results/formatters/http.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/tui/views/results/formatters/run_report.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/tui/views/results/formatters/summaries.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/tui/views/results/formatters/text.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/tui/views/results/formatters/traces.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/tui/views/results/tab.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/tui/widgets/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/tui/widgets/actions.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/tui/widgets/clipboard.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/tui/widgets/logs.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/web/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/web/_local_api.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/web/_proxy.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/web/_serializers.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/web/_static.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/interfaces/web/static/.gitignore +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/models/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/models/build.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/models/completions/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/models/completions/adk.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/models/completions/browser.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/models/completions/claude.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/models/completions/litellm.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/models/completions/web.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/models/config.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/models/connect.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/models/embeddings.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/models/factory.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/models/guardrail.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/models/model.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/models/provider_config.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/models/response.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/models/retry.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/models/target_params.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/orchestrator/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/orchestrator/campaign/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/orchestrator/campaign/audit.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/orchestrator/campaign/loader.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/orchestrator/campaign/preflight.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/orchestrator/campaign/resolve.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/orchestrator/campaign/results.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/orchestrator/campaign/runner.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/orchestrator/campaign/spec.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/orchestrator/campaign/tracking.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/orchestrator/planning/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/orchestrator/planning/catalog.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/orchestrator/planning/planner.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/orchestrator/planning/web.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/agent/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/agent/agent_create.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/agent/agent_destroy.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/agent/agent_list.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/agent/agent_partial_update.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/agent/agent_retrieve.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/agent/agent_update.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/apilogs/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/apilogs/apilogs_list.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/apilogs/apilogs_retrieve.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/apilogs/apilogs_summary_retrieve.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/attack/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/attack/attack_create.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/attack/attack_destroy.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/attack/attack_list.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/attack/attack_partial_update.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/attack/attack_retrieve.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/attack/attack_update.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/checkout/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/checkout/checkout_create.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/generate/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/generate/v1_chat_completions_create.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/judge/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/judge/judge_create.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/key/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/key/key_context_retrieve.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/key/key_create.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/key/key_destroy.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/key/key_list.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/key/key_retrieve.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/models.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/organization/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/organization/organization_create.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/organization/organization_destroy.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/organization/organization_list.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/organization/organization_me_retrieve.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/organization/organization_partial_update.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/organization/organization_retrieve.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/organization/organization_update.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/result/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/result/result_create.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/result/result_destroy.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/result/result_list.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/result/result_partial_update.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/result/result_retrieve.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/result/result_trace_create.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/result/result_update.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/run/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/run/run_create.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/run/run_destroy.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/run/run_list.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/run/run_partial_update.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/run/run_result_create.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/run/run_retrieve.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/run/run_run_tests_create.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/run/run_update.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/scripts/generate.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/scripts/generate.sh +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/scripts/openapi-python-client.yaml +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/user/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/user/user_create.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/user/user_destroy.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/user/user_list.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/user/user_me_retrieve.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/user/user_me_update.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/user/user_partial_update.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/user/user_retrieve.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/api/user/user_update.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/client.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/errors.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/_http/types.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/buckets.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/local.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/records.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/remote.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/storage/store.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/tracking/__init__.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/tracking/evaluation.py +0 -0
- {hackagent-0.15.0 → hackagent-0.16.0}/hackagent/tracking/serialize.py +0 -0
|
@@ -72,6 +72,7 @@ htmlcov/
|
|
|
72
72
|
.cache
|
|
73
73
|
nosetests.xml
|
|
74
74
|
coverage.xml
|
|
75
|
+
coverage.json
|
|
75
76
|
*.cover
|
|
76
77
|
.hypothesis/
|
|
77
78
|
.pytest_cache/
|
|
@@ -150,3 +151,7 @@ snapshot_report.html
|
|
|
150
151
|
# Web UI bundle (built by scripts/build_webui.sh)
|
|
151
152
|
hackagent/interfaces/web/static/*
|
|
152
153
|
!hackagent/interfaces/web/static/.gitignore
|
|
154
|
+
|
|
155
|
+
# Results exported from the TUI (hackagent/interfaces/tui/views/results/export.py)
|
|
156
|
+
hackagent_results_*.csv
|
|
157
|
+
hackagent_results_*.json
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: hackagent
|
|
3
|
+
Version: 0.16.0
|
|
4
|
+
Summary: HackAgent is an open-source security toolkit to detect vulnerabilities of your AI Agents.
|
|
5
|
+
Author-email: AI Security Lab <ais@ai4i.it>
|
|
6
|
+
License: Apache-2.0
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Keywords: agents,ai,security,testing,vulnerabilities
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Requires-Python: >=3.10
|
|
18
|
+
Requires-Dist: click>=8.1.0
|
|
19
|
+
Requires-Dist: httpx>=0.27.0
|
|
20
|
+
Requires-Dist: litellm>=1.69.2
|
|
21
|
+
Requires-Dist: openai>=1.0.0
|
|
22
|
+
Requires-Dist: pydantic[email]>=2.0
|
|
23
|
+
Requires-Dist: python-dateutil>=2.8.0
|
|
24
|
+
Requires-Dist: pyyaml>=6.0.0
|
|
25
|
+
Requires-Dist: rich>=14.0.0
|
|
26
|
+
Provides-Extra: browser
|
|
27
|
+
Requires-Dist: playwright>=1.40; extra == 'browser'
|
|
28
|
+
Provides-Extra: hf
|
|
29
|
+
Requires-Dist: datasets>=2.14.0; extra == 'hf'
|
|
30
|
+
Provides-Extra: rag
|
|
31
|
+
Requires-Dist: faiss-cpu>=1.13.2; extra == 'rag'
|
|
32
|
+
Requires-Dist: numpy>=1.26; extra == 'rag'
|
|
33
|
+
Provides-Extra: tui
|
|
34
|
+
Requires-Dist: textual>=1.0.0; extra == 'tui'
|
|
35
|
+
Provides-Extra: vision
|
|
36
|
+
Requires-Dist: pillow>=10.0.0; extra == 'vision'
|
|
37
|
+
Provides-Extra: web
|
|
38
|
+
Requires-Dist: flask>=3.1.3; extra == 'web'
|
|
39
|
+
Requires-Dist: hackagent-webui<1.0,>=0.2; extra == 'web'
|
|
40
|
+
Description-Content-Type: text/markdown
|
|
41
|
+
|
|
42
|
+
<div align="center">
|
|
43
|
+
|
|
44
|
+
<img src="https://docs.hackagent.dev/img/banner.svg" alt="HackAgent" width="800">
|
|
45
|
+
|
|
46
|
+
**The open-source red-team toolkit for AI models and agents**
|
|
47
|
+
|
|
48
|
+
[Docs](https://docs.hackagent.dev/) · [App](https://app.hackagent.dev/) · [API](https://api.hackagent.dev/schema/redoc)
|
|
49
|
+
|
|
50
|
+
[](https://pypi.org/project/hackagent/)
|
|
51
|
+

|
|
52
|
+

|
|
53
|
+

|
|
54
|
+

|
|
55
|
+
|
|
56
|
+
</div>
|
|
57
|
+
|
|
58
|
+
HackAgent attacks your AI model or agent with research-backed techniques —
|
|
59
|
+
jailbreaks, prompt injection, tool misuse — and has judge models score every
|
|
60
|
+
reply. You get a measured success rate per attack, so you can see how exposed a
|
|
61
|
+
target is and whether a fix helped.
|
|
62
|
+
|
|
63
|
+
## See it run
|
|
64
|
+
|
|
65
|
+
**Terminal UI.** Start from an example, change what you need, run it.
|
|
66
|
+
|
|
67
|
+
<img src="https://raw.githubusercontent.com/AISecurityLab/hackagent/main/docs/static/gifs/hackagent-tui.gif" alt="Building and running a campaign in the HackAgent terminal UI" width="100%">
|
|
68
|
+
|
|
69
|
+
**Command line.** The same campaign is one YAML file you can edit, check and run, in a shell or in CI.
|
|
70
|
+
|
|
71
|
+
<img src="https://raw.githubusercontent.com/AISecurityLab/hackagent/main/docs/static/gifs/hackagent-cli.gif" alt="Copying, editing, validating and running a campaign from the command line" width="100%">
|
|
72
|
+
|
|
73
|
+
**Dashboard.** Browse runs, results and traces with `hackagent web`, or on [app.hackagent.dev](https://app.hackagent.dev/).
|
|
74
|
+
|
|
75
|
+
<img src="https://raw.githubusercontent.com/AISecurityLab/hackagent/main/docs/static/gifs/hackagent-dashboard.gif" alt="Browsing campaign results in the HackAgent dashboard" width="100%">
|
|
76
|
+
|
|
77
|
+
## Quick start
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
pip install 'hackagent[tui]'
|
|
81
|
+
hackagent # opens the terminal UI
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Or run an example end to end, fully local, with [Ollama](https://ollama.com):
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
ollama pull gemma3:4b
|
|
88
|
+
hackagent examples copy h4rm3l-demo
|
|
89
|
+
hackagent campaign run h4rm3l-demo.yaml
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
No API key needed: results go to a local database unless a campaign says
|
|
93
|
+
otherwise.
|
|
94
|
+
|
|
95
|
+
## Learn more
|
|
96
|
+
|
|
97
|
+
- [Installation](https://docs.hackagent.dev/getting-started/installation) — extras, and standalone binaries that need no Python
|
|
98
|
+
- [Your first campaign](https://docs.hackagent.dev/getting-started/first-campaign) — write, check and run one
|
|
99
|
+
- [Concepts](https://docs.hackagent.dev/concepts) — attacks, judges and how a run works
|
|
100
|
+
- [Attacks](https://docs.hackagent.dev/reference/attacks) and the [campaign file reference](https://docs.hackagent.dev/reference/campaign)
|
|
101
|
+
- [Dashboard](https://docs.hackagent.dev/getting-started/dashboard) — `hackagent web`, locally or against your account
|
|
102
|
+
|
|
103
|
+
Questions? Join the [discussions](https://github.com/AISecurityLab/hackagent/discussions) or email ais@ai4i.it.
|
|
104
|
+
|
|
105
|
+
## Responsible use
|
|
106
|
+
|
|
107
|
+
HackAgent is for authorized security testing only. Test systems you own or
|
|
108
|
+
have written permission to test, and report what you find through coordinated
|
|
109
|
+
disclosure. Read the [responsible disclosure guidelines](https://docs.hackagent.dev/security/responsible-disclosure)
|
|
110
|
+
and our [security policy](SECURITY.md).
|
|
111
|
+
|
|
112
|
+
## Contributing
|
|
113
|
+
|
|
114
|
+
Contributions are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) and
|
|
115
|
+
[CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md).
|
|
116
|
+
|
|
117
|
+
## License
|
|
118
|
+
|
|
119
|
+
Licensed under Apache-2.0. See [LICENSE](LICENSE). HackAgent is intended for
|
|
120
|
+
security research and AI safety improvement; the authors are not responsible
|
|
121
|
+
for misuse.
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
<img src="https://docs.hackagent.dev/img/banner.svg" alt="HackAgent" width="800">
|
|
4
|
+
|
|
5
|
+
**The open-source red-team toolkit for AI models and agents**
|
|
6
|
+
|
|
7
|
+
[Docs](https://docs.hackagent.dev/) · [App](https://app.hackagent.dev/) · [API](https://api.hackagent.dev/schema/redoc)
|
|
8
|
+
|
|
9
|
+
[](https://pypi.org/project/hackagent/)
|
|
10
|
+

|
|
11
|
+

|
|
12
|
+

|
|
13
|
+

|
|
14
|
+
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
HackAgent attacks your AI model or agent with research-backed techniques —
|
|
18
|
+
jailbreaks, prompt injection, tool misuse — and has judge models score every
|
|
19
|
+
reply. You get a measured success rate per attack, so you can see how exposed a
|
|
20
|
+
target is and whether a fix helped.
|
|
21
|
+
|
|
22
|
+
## See it run
|
|
23
|
+
|
|
24
|
+
**Terminal UI.** Start from an example, change what you need, run it.
|
|
25
|
+
|
|
26
|
+
<img src="https://raw.githubusercontent.com/AISecurityLab/hackagent/main/docs/static/gifs/hackagent-tui.gif" alt="Building and running a campaign in the HackAgent terminal UI" width="100%">
|
|
27
|
+
|
|
28
|
+
**Command line.** The same campaign is one YAML file you can edit, check and run, in a shell or in CI.
|
|
29
|
+
|
|
30
|
+
<img src="https://raw.githubusercontent.com/AISecurityLab/hackagent/main/docs/static/gifs/hackagent-cli.gif" alt="Copying, editing, validating and running a campaign from the command line" width="100%">
|
|
31
|
+
|
|
32
|
+
**Dashboard.** Browse runs, results and traces with `hackagent web`, or on [app.hackagent.dev](https://app.hackagent.dev/).
|
|
33
|
+
|
|
34
|
+
<img src="https://raw.githubusercontent.com/AISecurityLab/hackagent/main/docs/static/gifs/hackagent-dashboard.gif" alt="Browsing campaign results in the HackAgent dashboard" width="100%">
|
|
35
|
+
|
|
36
|
+
## Quick start
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pip install 'hackagent[tui]'
|
|
40
|
+
hackagent # opens the terminal UI
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Or run an example end to end, fully local, with [Ollama](https://ollama.com):
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
ollama pull gemma3:4b
|
|
47
|
+
hackagent examples copy h4rm3l-demo
|
|
48
|
+
hackagent campaign run h4rm3l-demo.yaml
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
No API key needed: results go to a local database unless a campaign says
|
|
52
|
+
otherwise.
|
|
53
|
+
|
|
54
|
+
## Learn more
|
|
55
|
+
|
|
56
|
+
- [Installation](https://docs.hackagent.dev/getting-started/installation) — extras, and standalone binaries that need no Python
|
|
57
|
+
- [Your first campaign](https://docs.hackagent.dev/getting-started/first-campaign) — write, check and run one
|
|
58
|
+
- [Concepts](https://docs.hackagent.dev/concepts) — attacks, judges and how a run works
|
|
59
|
+
- [Attacks](https://docs.hackagent.dev/reference/attacks) and the [campaign file reference](https://docs.hackagent.dev/reference/campaign)
|
|
60
|
+
- [Dashboard](https://docs.hackagent.dev/getting-started/dashboard) — `hackagent web`, locally or against your account
|
|
61
|
+
|
|
62
|
+
Questions? Join the [discussions](https://github.com/AISecurityLab/hackagent/discussions) or email ais@ai4i.it.
|
|
63
|
+
|
|
64
|
+
## Responsible use
|
|
65
|
+
|
|
66
|
+
HackAgent is for authorized security testing only. Test systems you own or
|
|
67
|
+
have written permission to test, and report what you find through coordinated
|
|
68
|
+
disclosure. Read the [responsible disclosure guidelines](https://docs.hackagent.dev/security/responsible-disclosure)
|
|
69
|
+
and our [security policy](SECURITY.md).
|
|
70
|
+
|
|
71
|
+
## Contributing
|
|
72
|
+
|
|
73
|
+
Contributions are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) and
|
|
74
|
+
[CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md).
|
|
75
|
+
|
|
76
|
+
## License
|
|
77
|
+
|
|
78
|
+
Licensed under Apache-2.0. See [LICENSE](LICENSE). HackAgent is intended for
|
|
79
|
+
security research and AI safety improvement; the authors are not responsible
|
|
80
|
+
for misuse.
|
{hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/static/h4rm3l/decorators/base.py
RENAMED
|
@@ -9,13 +9,27 @@ import inspect
|
|
|
9
9
|
from collections.abc import Awaitable
|
|
10
10
|
from typing import TypeAlias
|
|
11
11
|
|
|
12
|
-
from numpy.random import RandomState
|
|
13
|
-
|
|
14
12
|
from ...base import Completion
|
|
15
13
|
|
|
16
14
|
DecorationResult: TypeAlias = str | Awaitable[str]
|
|
17
15
|
|
|
18
16
|
|
|
17
|
+
def _random_state(seed: int):
|
|
18
|
+
"""A seeded numpy RandomState, imported when the first decorator is built.
|
|
19
|
+
|
|
20
|
+
Not at module level, so the attack's settings can be read without numpy,
|
|
21
|
+
as the TUI and campaign validation do for every attack.
|
|
22
|
+
"""
|
|
23
|
+
try:
|
|
24
|
+
from numpy.random import RandomState
|
|
25
|
+
except ImportError as exc:
|
|
26
|
+
raise ImportError(
|
|
27
|
+
"numpy is required for the h4rm3l attack. "
|
|
28
|
+
"Install with: pip install 'hackagent[rag]'"
|
|
29
|
+
) from exc
|
|
30
|
+
return RandomState(seed=seed)
|
|
31
|
+
|
|
32
|
+
|
|
19
33
|
class PromptDecorator:
|
|
20
34
|
"""Base class for all h4rm3l decorators.
|
|
21
35
|
|
|
@@ -24,7 +38,7 @@ class PromptDecorator:
|
|
|
24
38
|
"""
|
|
25
39
|
|
|
26
40
|
def __init__(self, seed: int = 42) -> None:
|
|
27
|
-
self._random_state =
|
|
41
|
+
self._random_state = _random_state(seed)
|
|
28
42
|
self._chain: list[PromptDecorator] = [self]
|
|
29
43
|
|
|
30
44
|
def decorate(self, prompt: str) -> DecorationResult:
|
{hackagent-0.15.0 → hackagent-0.16.0}/hackagent/attacks/techniques/static/mml/image_encoder.py
RENAMED
|
@@ -15,35 +15,52 @@ All images are returned as base64-encoded data URLs suitable for inclusion
|
|
|
15
15
|
in multimodal LLM API requests.
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
18
20
|
import base64
|
|
19
21
|
import io
|
|
20
22
|
import random
|
|
21
23
|
import textwrap
|
|
22
|
-
from
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
24
|
+
from types import ModuleType
|
|
25
|
+
from typing import TYPE_CHECKING, Any, Dict, List
|
|
26
|
+
|
|
27
|
+
if TYPE_CHECKING:
|
|
28
|
+
from PIL import Image, ImageFont
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _pil() -> ModuleType:
|
|
32
|
+
"""Pillow, imported when the first image is drawn.
|
|
33
|
+
|
|
34
|
+
Not at module level, so the attack's settings can be read without the
|
|
35
|
+
vision extra, as the TUI and campaign validation do for every attack.
|
|
36
|
+
"""
|
|
37
|
+
try:
|
|
38
|
+
import PIL.Image
|
|
39
|
+
import PIL.ImageDraw
|
|
40
|
+
import PIL.ImageFont
|
|
41
|
+
except ImportError as exc:
|
|
42
|
+
raise ImportError(
|
|
43
|
+
"Pillow is required for the MML attack. "
|
|
44
|
+
"Install with: pip install 'hackagent[vision]'"
|
|
45
|
+
) from exc
|
|
46
|
+
return PIL
|
|
31
47
|
|
|
32
48
|
|
|
33
49
|
def _get_font(font_size: int) -> ImageFont.FreeTypeFont:
|
|
34
50
|
"""Load a monospace font, falling back to the default if unavailable."""
|
|
51
|
+
fonts = _pil().ImageFont
|
|
35
52
|
try:
|
|
36
|
-
return
|
|
53
|
+
return fonts.truetype("DejaVuSansMono.ttf", font_size)
|
|
37
54
|
except (OSError, IOError):
|
|
38
55
|
try:
|
|
39
|
-
return
|
|
56
|
+
return fonts.truetype("DejaVuSans.ttf", font_size)
|
|
40
57
|
except (OSError, IOError):
|
|
41
58
|
try:
|
|
42
|
-
return
|
|
59
|
+
return fonts.truetype(
|
|
43
60
|
"/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", font_size
|
|
44
61
|
)
|
|
45
62
|
except (OSError, IOError):
|
|
46
|
-
return
|
|
63
|
+
return fonts.load_default()
|
|
47
64
|
|
|
48
65
|
|
|
49
66
|
def _render_text_to_image(
|
|
@@ -67,8 +84,9 @@ def _render_text_to_image(
|
|
|
67
84
|
Returns:
|
|
68
85
|
A PIL Image with the text rendered on it.
|
|
69
86
|
"""
|
|
70
|
-
|
|
71
|
-
|
|
87
|
+
pil = _pil()
|
|
88
|
+
img = pil.Image.new("RGB", (width, height), color=background_color)
|
|
89
|
+
draw = pil.ImageDraw.Draw(img)
|
|
72
90
|
font = _get_font(font_size)
|
|
73
91
|
|
|
74
92
|
# Wrap text to fit within the image width
|
|
@@ -255,7 +273,7 @@ def encode_mirror(
|
|
|
255
273
|
prompt, image_width, image_height, font_size, background_color, text_color
|
|
256
274
|
)
|
|
257
275
|
# Mirror horizontally
|
|
258
|
-
img = img.transpose(Image.FLIP_LEFT_RIGHT)
|
|
276
|
+
img = img.transpose(_pil().Image.FLIP_LEFT_RIGHT)
|
|
259
277
|
|
|
260
278
|
words = prompt.split()
|
|
261
279
|
scrambled_words = words.copy()
|
|
@@ -407,7 +425,7 @@ def encode_mixed(
|
|
|
407
425
|
)
|
|
408
426
|
|
|
409
427
|
# Apply mirror and rotation
|
|
410
|
-
img = img.transpose(Image.FLIP_LEFT_RIGHT)
|
|
428
|
+
img = img.transpose(_pil().Image.FLIP_LEFT_RIGHT)
|
|
411
429
|
img = img.rotate(180)
|
|
412
430
|
|
|
413
431
|
# Scramble original words
|
|
@@ -53,13 +53,13 @@ Then run:
|
|
|
53
53
|
| Config key | Maps to | Default |
|
|
54
54
|
|---|---|---|
|
|
55
55
|
| `name` (required) | `-m <model>` | — |
|
|
56
|
-
| `binary` | argv[0], checked with `shutil.which` at construction | `hermes` |
|
|
56
|
+
| `binary` | argv[0], checked with `shutil.which` at construction. `ollama` starts Hermes with `ollama launch hermes --model <name>` | `hermes` |
|
|
57
57
|
| `provider` | `--provider <provider>` | unset |
|
|
58
58
|
| `cwd` | working directory Hermes operates in | unset |
|
|
59
59
|
| `timeout` | `subprocess.run(..., timeout=)` seconds | `600` |
|
|
60
|
-
| `ignore_user_config` | `--ignore-user-config` | `True` |
|
|
60
|
+
| `ignore_user_config` | `--ignore-user-config` | `True`, or `False` when `binary` is `ollama` |
|
|
61
61
|
| `safe_mode` | `--safe-mode` | `False` |
|
|
62
|
-
| `source` | `--source <source>` |
|
|
62
|
+
| `source` | `--source <source>` | unset |
|
|
63
63
|
| `extra_args` | appended raw flags | `[]` |
|
|
64
64
|
|
|
65
65
|
---
|
|
@@ -71,9 +71,10 @@ Unlike Claude Code, Hermes is stateful: it keeps long-term memory in `~/.hermes/
|
|
|
71
71
|
The adapter therefore defaults to isolation:
|
|
72
72
|
|
|
73
73
|
- `--ignore-user-config` is always passed unless you explicitly set `"ignore_user_config": False`, so the target uses defaults plus `.env` credentials only and never reads `~/.hermes/config.yaml`.
|
|
74
|
+
- Through Ollama (`binary: ollama`) `--ignore-user-config` is off by default: `ollama launch hermes` writes the model into `~/.hermes/config.yaml`, so Hermes has to read it. Isolate the run with a dedicated `hermes profile` instead.
|
|
74
75
|
- `-r`/`--resume` and `-c`/`--continue` are never passed, so every attack turn is a fresh session.
|
|
75
76
|
- `"safe_mode": True` opts into `--safe-mode` for maximum isolation (all customizations disabled).
|
|
76
|
-
- `--source
|
|
77
|
+
- `--source` is not passed by default: recent Hermes versions accept it only under `hermes chat`, not with `-z`. Set `source` if your version takes it.
|
|
77
78
|
|
|
78
79
|
For stronger separation still, point `cwd` at a scratch directory and/or run the target under a dedicated `hermes profile` so the operator's real profile, memory and skills are never touched.
|
|
79
80
|
|
|
@@ -82,7 +83,8 @@ For stronger separation still, point `cwd` at a scratch directory and/or run the
|
|
|
82
83
|
### Notes
|
|
83
84
|
|
|
84
85
|
- `hermes -z` returns bare text with no structured metadata (no session id, cost or exit reason), so the adapter relies on exit codes: `0` success, `1` delivery/backend failure, `2` usage error. A non-zero exit with usable stdout is captured as the target's response (a refusal is a legitimate response to judge); exit `2` always fails loudly.
|
|
85
|
-
- The prompt is
|
|
86
|
+
- The prompt is passed as `--oneshot=<prompt>`, the value of `-z`. Joined to the option with `=`, an adversarial payload starting with `-` is not parsed as a CLI flag.
|
|
87
|
+
- As one argument, the prompt is limited by the OS: about 127 KiB on Linux and macOS, 30,000 bytes on Windows. A longer prompt fails that turn with an error instead of reaching Hermes.
|
|
86
88
|
- The `endpoint` field is present for HackAgent compatibility but is ignored for this local setup.
|
|
87
89
|
- If the configured binary is not on `PATH`, the setup fails before the attack runs.
|
|
88
90
|
- `hermes serve` (a headless backend over JSON-RPC/WebSocket) is out of scope here; this example covers the local CLI-driven path only.
|
|
@@ -8,6 +8,7 @@ Launch ready-to-run example scenarios from the CLI.
|
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
10
|
import importlib
|
|
11
|
+
import re
|
|
11
12
|
import os
|
|
12
13
|
import socket
|
|
13
14
|
import shutil
|
|
@@ -17,6 +18,7 @@ import time
|
|
|
17
18
|
from dataclasses import dataclass
|
|
18
19
|
from pathlib import Path
|
|
19
20
|
from types import ModuleType
|
|
21
|
+
from typing import Optional
|
|
20
22
|
from urllib.error import URLError
|
|
21
23
|
from urllib.parse import urljoin
|
|
22
24
|
from urllib.request import urlopen
|
|
@@ -513,10 +515,56 @@ def list_examples():
|
|
|
513
515
|
console.print(f" [dim]{line}[/dim]")
|
|
514
516
|
console.print(
|
|
515
517
|
"\n[dim]Run one with:[/dim] hackagent examples run <name>\n"
|
|
518
|
+
"[dim]Or copy it here to edit:[/dim] hackagent examples copy <name>\n"
|
|
516
519
|
"[dim]A name's last part is enough when it is unique.[/dim]"
|
|
517
520
|
)
|
|
518
521
|
|
|
519
522
|
|
|
523
|
+
#: Where the docs site serves the campaign JSON Schema.
|
|
524
|
+
CAMPAIGN_SCHEMA_URL = "https://docs.hackagent.dev/schema/campaign.schema.json"
|
|
525
|
+
|
|
526
|
+
#: An editor schema hint pointing at a relative path, as the examples have.
|
|
527
|
+
_SCHEMA_HINT = re.compile(r"^(# yaml-language-server: \$schema=)(?!https?://)\S+", re.M)
|
|
528
|
+
|
|
529
|
+
|
|
530
|
+
@examples.command(name="copy")
|
|
531
|
+
@click.argument("name")
|
|
532
|
+
@click.argument("destination", required=False, type=click.Path(path_type=Path))
|
|
533
|
+
@click.option("--force", is_flag=True, help="Overwrite a file that is already there.")
|
|
534
|
+
@handle_errors
|
|
535
|
+
def copy_example(name: str, destination: Optional[Path], force: bool):
|
|
536
|
+
"""📄 Copy an example campaign here, to edit and run as your own.
|
|
537
|
+
|
|
538
|
+
DESTINATION is a file or a folder, the current folder by default.
|
|
539
|
+
"""
|
|
540
|
+
key, source = _resolve_example_name(name)
|
|
541
|
+
target = destination or Path(".")
|
|
542
|
+
if target.is_dir():
|
|
543
|
+
target = target / source.name
|
|
544
|
+
if target.exists() and not force:
|
|
545
|
+
raise click.ClickException(
|
|
546
|
+
f"{target} already exists; use --force to replace it."
|
|
547
|
+
)
|
|
548
|
+
# Copied as it is, comments included: they explain the example. Only the
|
|
549
|
+
# editor's schema hint changes, from a path inside this repository to the
|
|
550
|
+
# schema the docs site publishes.
|
|
551
|
+
text = source.read_text(encoding="utf-8")
|
|
552
|
+
text = _SCHEMA_HINT.sub(rf"\g<1>{CAMPAIGN_SCHEMA_URL}", text, count=1)
|
|
553
|
+
target.write_text(text, encoding="utf-8")
|
|
554
|
+
|
|
555
|
+
console.print(f"[green]Copied[/green] {key} → {target}")
|
|
556
|
+
folder = key.rsplit("/", 1)[0] if "/" in key else ""
|
|
557
|
+
if folder in _TARGETS or folder in _MANUAL_TARGETS:
|
|
558
|
+
console.print(
|
|
559
|
+
"[yellow]Its agent is not copied: start it the way "
|
|
560
|
+
f"`hackagent examples run {key}` does, or point the target elsewhere.[/yellow]"
|
|
561
|
+
)
|
|
562
|
+
console.print(
|
|
563
|
+
f"[dim]Edit it, then run it with:[/dim] hackagent campaign run {target}",
|
|
564
|
+
soft_wrap=True,
|
|
565
|
+
)
|
|
566
|
+
|
|
567
|
+
|
|
520
568
|
@examples.command(name="run")
|
|
521
569
|
@click.argument("name")
|
|
522
570
|
@handle_errors
|
|
@@ -13,6 +13,7 @@ app of its own, opened by starting ``HackAgentTUI`` on it, which is how the
|
|
|
13
13
|
welcome screen reaches past results.
|
|
14
14
|
"""
|
|
15
15
|
|
|
16
|
+
import os
|
|
16
17
|
from pathlib import Path
|
|
17
18
|
from typing import Any
|
|
18
19
|
|
|
@@ -28,6 +29,27 @@ from hackagent.interfaces.tui.views.config import ConfigTab
|
|
|
28
29
|
from hackagent.interfaces.tui.views.results import ResultsTab
|
|
29
30
|
|
|
30
31
|
|
|
32
|
+
def _start_multiprocessing_tracker() -> None:
|
|
33
|
+
"""Start multiprocessing's resource tracker while stderr is still a file.
|
|
34
|
+
|
|
35
|
+
Textual replaces ``sys.stderr`` with an object that has no file
|
|
36
|
+
descriptor. The first multiprocessing lock made after that starts the
|
|
37
|
+
tracker, which hands its child stderr's descriptor and fails with
|
|
38
|
+
"bad value(s) in fds_to_keep". tqdm makes such a lock whenever
|
|
39
|
+
``datasets`` loads a Hugging Face dataset, so a campaign whose goals come
|
|
40
|
+
from a preset could not run in the TUI. Started here, the tracker is
|
|
41
|
+
already running when that lock is made.
|
|
42
|
+
"""
|
|
43
|
+
if os.name != "posix": # Windows has no resource tracker.
|
|
44
|
+
return
|
|
45
|
+
from multiprocessing import resource_tracker
|
|
46
|
+
|
|
47
|
+
try:
|
|
48
|
+
resource_tracker.ensure_running()
|
|
49
|
+
except Exception: # noqa: BLE001 - never stop the TUI from opening over it
|
|
50
|
+
pass
|
|
51
|
+
|
|
52
|
+
|
|
31
53
|
class HackAgentTUI(App):
|
|
32
54
|
"""HackAgent Terminal User Interface Application"""
|
|
33
55
|
|
|
@@ -204,6 +226,10 @@ class HackAgentTUI(App):
|
|
|
204
226
|
"""Expose the HackAgent brand palette as CSS variables."""
|
|
205
227
|
return {**super().get_css_variables(), **css_variables()}
|
|
206
228
|
|
|
229
|
+
def run(self, *args: Any, **kwargs: Any) -> Any:
|
|
230
|
+
_start_multiprocessing_tracker()
|
|
231
|
+
return super().run(*args, **kwargs)
|
|
232
|
+
|
|
207
233
|
def compose(self) -> ComposeResult:
|
|
208
234
|
"""One view and a footer.
|
|
209
235
|
|
|
@@ -62,6 +62,9 @@ class FieldRow(Horizontal):
|
|
|
62
62
|
self.draft = draft
|
|
63
63
|
self.box = box
|
|
64
64
|
self.issue: Optional[str] = None
|
|
65
|
+
# Kept rather than queried: Textual can remove the row's children
|
|
66
|
+
# before a pending mount refreshes it, as when the app closes at once.
|
|
67
|
+
self._state = Static("", classes="state")
|
|
65
68
|
|
|
66
69
|
@property
|
|
67
70
|
def path(self) -> Path:
|
|
@@ -70,7 +73,7 @@ class FieldRow(Horizontal):
|
|
|
70
73
|
def compose(self) -> ComposeResult:
|
|
71
74
|
yield Static(_label_markup(self.field.label_in(self.box)), classes="label")
|
|
72
75
|
yield self._editor()
|
|
73
|
-
yield
|
|
76
|
+
yield self._state
|
|
74
77
|
|
|
75
78
|
def on_mount(self) -> None:
|
|
76
79
|
self.refresh_state()
|
|
@@ -159,7 +162,8 @@ class FieldRow(Horizontal):
|
|
|
159
162
|
elif self.field.kind == "tristate":
|
|
160
163
|
self._commit(event.value == "true")
|
|
161
164
|
else:
|
|
162
|
-
|
|
165
|
+
# The widget holds text; the campaign needs the schema's type.
|
|
166
|
+
self._commit(self.field.choice_value(str(event.value)))
|
|
163
167
|
|
|
164
168
|
def on_text_area_changed(self, event: TextArea.Changed) -> None:
|
|
165
169
|
event.stop()
|
|
@@ -203,7 +207,7 @@ class FieldRow(Horizontal):
|
|
|
203
207
|
# No default and not required: leaving it out sends nothing, and
|
|
204
208
|
# whatever is on the other end picks.
|
|
205
209
|
text = "[dim]not sent[/dim]"
|
|
206
|
-
self.
|
|
210
|
+
self._state.update(text)
|
|
207
211
|
|
|
208
212
|
|
|
209
213
|
def _label_markup(label: str) -> str:
|
|
@@ -80,6 +80,9 @@ class FieldDef:
|
|
|
80
80
|
default: Any
|
|
81
81
|
description: str
|
|
82
82
|
choices: tuple[str, ...] = ()
|
|
83
|
+
#: What each choice stands for, in the same order: ``2`` for the choice
|
|
84
|
+
#: ``"2"`` of ``Literal[1, 2]``. Empty when the choices are the values.
|
|
85
|
+
choice_values: tuple[Any, ...] = ()
|
|
83
86
|
advanced: bool = False
|
|
84
87
|
#: The model this field belongs to. Two models can share a field name, so
|
|
85
88
|
#: anything keyed on fields must key on this too.
|
|
@@ -123,6 +126,13 @@ class FieldDef:
|
|
|
123
126
|
return ", ".join(str(item) for item in self.default)
|
|
124
127
|
return str(self.default)
|
|
125
128
|
|
|
129
|
+
def choice_value(self, choice: str) -> Any:
|
|
130
|
+
"""The value a choice stands for, with the type the schema expects."""
|
|
131
|
+
for text, value in zip(self.choices, self.choice_values):
|
|
132
|
+
if text == choice:
|
|
133
|
+
return value
|
|
134
|
+
return choice
|
|
135
|
+
|
|
126
136
|
def is_default(self, value: Any) -> bool:
|
|
127
137
|
"""Whether ``value`` is what the schema would use anyway."""
|
|
128
138
|
if self.default is MISSING:
|
|
@@ -185,6 +195,15 @@ def _kind(annotation: Any) -> tuple[Optional[str], tuple[str, ...]]:
|
|
|
185
195
|
return None, ()
|
|
186
196
|
|
|
187
197
|
|
|
198
|
+
def _choice_values(annotation: Any) -> tuple[Any, ...]:
|
|
199
|
+
"""The values behind a choice field's labels, as :func:`_kind` lists them."""
|
|
200
|
+
if get_origin(annotation) is Literal:
|
|
201
|
+
return get_args(annotation)
|
|
202
|
+
if isinstance(annotation, type) and issubclass(annotation, enum.Enum):
|
|
203
|
+
return tuple(member.value for member in annotation)
|
|
204
|
+
return ()
|
|
205
|
+
|
|
206
|
+
|
|
188
207
|
def discriminated_variants(
|
|
189
208
|
info: FieldInfo,
|
|
190
209
|
) -> tuple[Optional[str], dict[str, type[BaseModel]]]:
|
|
@@ -279,6 +298,7 @@ def model_fields(
|
|
|
279
298
|
default=default,
|
|
280
299
|
description=info.description or "",
|
|
281
300
|
choices=choices,
|
|
301
|
+
choice_values=_choice_values(annotation) if kind == "choice" else (),
|
|
282
302
|
advanced=bool(_advanced_flag(info)),
|
|
283
303
|
owner=model,
|
|
284
304
|
)
|
|
@@ -16,6 +16,7 @@ Subclasses set the class attributes, read their own options in
|
|
|
16
16
|
from __future__ import annotations
|
|
17
17
|
|
|
18
18
|
import asyncio
|
|
19
|
+
import os
|
|
19
20
|
import shutil
|
|
20
21
|
from abc import abstractmethod
|
|
21
22
|
from typing import Any, ClassVar, Dict, List, Mapping, Optional, Sequence
|
|
@@ -62,6 +63,16 @@ def last_user_text(messages: List[Dict[str, Any]]) -> Optional[str]:
|
|
|
62
63
|
return None
|
|
63
64
|
|
|
64
65
|
|
|
66
|
+
def is_ollama_launcher(binary: str) -> bool:
|
|
67
|
+
"""Whether ``binary`` is Ollama, which starts an agent with ``ollama launch``.
|
|
68
|
+
|
|
69
|
+
Only the executable's name counts, so an agent installed under a folder
|
|
70
|
+
called ``ollama`` still runs natively.
|
|
71
|
+
"""
|
|
72
|
+
name = os.path.basename(binary).lower()
|
|
73
|
+
return name in ("ollama", "ollama.exe")
|
|
74
|
+
|
|
75
|
+
|
|
65
76
|
class SubprocessCLIModel(Model):
|
|
66
77
|
"""A :class:`Model` that answers each turn by running a local CLI."""
|
|
67
78
|
|
|
@@ -192,5 +203,6 @@ __all__ = [
|
|
|
192
203
|
"CLIConfigurationError",
|
|
193
204
|
"CLIInteractionError",
|
|
194
205
|
"SubprocessCLIModel",
|
|
206
|
+
"is_ollama_launcher",
|
|
195
207
|
"last_user_text",
|
|
196
208
|
]
|
|
@@ -26,6 +26,7 @@ from hackagent.models.completions.cli import (
|
|
|
26
26
|
CLIConfigurationError,
|
|
27
27
|
CLIInteractionError,
|
|
28
28
|
SubprocessCLIModel,
|
|
29
|
+
is_ollama_launcher,
|
|
29
30
|
last_user_text,
|
|
30
31
|
)
|
|
31
32
|
|
|
@@ -194,9 +195,7 @@ def _get_codex_custom_llm_class():
|
|
|
194
195
|
def _build_argv(self) -> List[str]:
|
|
195
196
|
"""Assemble the CLI argv based on whether we use codex natively or via ollama."""
|
|
196
197
|
argv = [self.binary]
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
if is_ollama:
|
|
198
|
+
if is_ollama_launcher(self.binary):
|
|
200
199
|
# ollama arguments
|
|
201
200
|
argv.extend(["launch", "codex"])
|
|
202
201
|
if self.model:
|
|
@@ -213,6 +212,10 @@ def _get_codex_custom_llm_class():
|
|
|
213
212
|
if self.model:
|
|
214
213
|
argv.extend(["-m", self.model])
|
|
215
214
|
|
|
215
|
+
# Attacks run in throwaway folders, and codex exec refuses to start
|
|
216
|
+
# outside a Git repository without this.
|
|
217
|
+
argv.append("--skip-git-repo-check")
|
|
218
|
+
|
|
216
219
|
# Codex does not need an HTTP endpoint here. Prompt text is passed
|
|
217
220
|
# through stdin by _run, matching the Claude Code backend style.
|
|
218
221
|
|