hackagent 0.11.0__tar.gz → 0.12.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.
Files changed (472) hide show
  1. {hackagent-0.11.0 → hackagent-0.12.0}/.gitignore +6 -0
  2. {hackagent-0.11.0 → hackagent-0.12.0}/PKG-INFO +24 -2
  3. {hackagent-0.11.0 → hackagent-0.12.0}/README.md +22 -1
  4. hackagent-0.12.0/hackagent/_version.py +21 -0
  5. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/agent.py +246 -4
  6. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/base.py +5 -8
  7. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/evaluator/__init__.py +5 -0
  8. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/evaluator/base.py +14 -1
  9. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/evaluator/evaluation_step.py +319 -12
  10. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/evaluator/inline_step_judge.py +42 -8
  11. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/evaluator/judge_evaluators.py +194 -5
  12. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/evaluator/metrics.py +11 -3
  13. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/evaluator/sync.py +6 -1
  14. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/orchestrator.py +261 -78
  15. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/shared/prompt_parser.py +11 -4
  16. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/advprefix/attack.py +5 -3
  17. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/advprefix/config.py +5 -2
  18. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/autodan_turbo/attack.py +28 -15
  19. hackagent-0.11.0/hackagent/attacks/techniques/autodan_turbo/evaluation.py → hackagent-0.12.0/hackagent/attacks/techniques/autodan_turbo/autodan_eval.py +14 -51
  20. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/autodan_turbo/config.py +19 -4
  21. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/autodan_turbo/core.py +3 -2
  22. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/autodan_turbo/lifelong.py +14 -3
  23. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/autodan_turbo/warm_up.py +14 -3
  24. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/base.py +26 -3
  25. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/baseline/attack.py +15 -11
  26. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/baseline/config.py +1 -1
  27. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/baseline/generation.py +18 -23
  28. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/bon/attack.py +8 -4
  29. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/cipherchat/attack.py +14 -4
  30. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/config.py +2 -0
  31. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/fc/attack.py +21 -7
  32. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/fc/flowchart_renderer.py +561 -14
  33. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/flipattack/attack.py +10 -4
  34. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/h4rm3l/attack.py +51 -4
  35. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/indirect_prompt_injection/attack.py +5 -3
  36. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/indirect_prompt_injection/config.py +2 -1
  37. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/mml/attack.py +12 -4
  38. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/pair/attack.py +500 -270
  39. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/pair/config.py +28 -6
  40. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/pap/attack.py +8 -4
  41. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/rag/attack.py +47 -6
  42. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/rag/config.py +4 -0
  43. hackagent-0.12.0/hackagent/attacks/techniques/rag/jailbreak.py +439 -0
  44. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/static_template/attack.py +25 -20
  45. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/static_template/config.py +2 -2
  46. hackagent-0.11.0/hackagent/attacks/techniques/static_template/evaluation.py → hackagent-0.12.0/hackagent/attacks/techniques/static_template/static_eval.py +40 -144
  47. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/tap/attack.py +5 -3
  48. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/tap/generation.py +1 -1
  49. hackagent-0.11.0/hackagent/attacks/techniques/tap/evaluation.py → hackagent-0.12.0/hackagent/attacks/techniques/tap/tap_evaluation.py +14 -19
  50. hackagent-0.12.0/hackagent/attacks/types.py +190 -0
  51. hackagent-0.12.0/hackagent/cli/bootstrap.py +96 -0
  52. hackagent-0.12.0/hackagent/cli/commands/attack/__init__.py +66 -0
  53. hackagent-0.12.0/hackagent/cli/commands/attack/catalog.py +65 -0
  54. hackagent-0.12.0/hackagent/cli/commands/attack/chain.py +247 -0
  55. hackagent-0.12.0/hackagent/cli/commands/attack/config.py +109 -0
  56. hackagent-0.12.0/hackagent/cli/commands/attack/display.py +220 -0
  57. hackagent-0.12.0/hackagent/cli/commands/attack/group.py +119 -0
  58. hackagent-0.12.0/hackagent/cli/commands/attack/info.py +58 -0
  59. hackagent-0.12.0/hackagent/cli/commands/attack/options.py +82 -0
  60. hackagent-0.12.0/hackagent/cli/commands/attack/runner.py +175 -0
  61. hackagent-0.12.0/hackagent/cli/commands/attack/strategies.py +96 -0
  62. hackagent-0.12.0/hackagent/cli/commands/codex.py +291 -0
  63. hackagent-0.12.0/hackagent/cli/commands/datasets.py +236 -0
  64. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/cli/commands/examples.py +159 -91
  65. hackagent-0.12.0/hackagent/cli/commands/scan/__init__.py +47 -0
  66. hackagent-0.11.0/hackagent/cli/commands/scan.py → hackagent-0.12.0/hackagent/cli/commands/scan/command.py +7 -270
  67. hackagent-0.12.0/hackagent/cli/commands/scan/helpers.py +120 -0
  68. hackagent-0.12.0/hackagent/cli/commands/scan/quick.py +181 -0
  69. hackagent-0.12.0/hackagent/cli/help_page.py +143 -0
  70. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/cli/main.py +67 -229
  71. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/cli/tui/app.py +31 -26
  72. hackagent-0.12.0/hackagent/cli/tui/attack_specs/__init__.py +49 -0
  73. hackagent-0.12.0/hackagent/cli/tui/attack_specs/registry.py +33 -0
  74. hackagent-0.12.0/hackagent/cli/tui/attack_specs/specs/__init__.py +55 -0
  75. hackagent-0.12.0/hackagent/cli/tui/attack_specs/specs/advprefix.py +197 -0
  76. hackagent-0.12.0/hackagent/cli/tui/attack_specs/specs/autodan_turbo.py +150 -0
  77. hackagent-0.12.0/hackagent/cli/tui/attack_specs/specs/baseline.py +104 -0
  78. hackagent-0.12.0/hackagent/cli/tui/attack_specs/specs/bon.py +131 -0
  79. hackagent-0.12.0/hackagent/cli/tui/attack_specs/specs/cipherchat.py +215 -0
  80. hackagent-0.12.0/hackagent/cli/tui/attack_specs/specs/fc.py +65 -0
  81. hackagent-0.12.0/hackagent/cli/tui/attack_specs/specs/flipattack.py +107 -0
  82. hackagent-0.12.0/hackagent/cli/tui/attack_specs/specs/h4rm3l.py +100 -0
  83. hackagent-0.12.0/hackagent/cli/tui/attack_specs/specs/mml.py +121 -0
  84. hackagent-0.12.0/hackagent/cli/tui/attack_specs/specs/pair.py +142 -0
  85. hackagent-0.12.0/hackagent/cli/tui/attack_specs/specs/pap.py +139 -0
  86. hackagent-0.12.0/hackagent/cli/tui/attack_specs/specs/static_template.py +146 -0
  87. hackagent-0.12.0/hackagent/cli/tui/attack_specs/specs/tap.py +119 -0
  88. hackagent-0.12.0/hackagent/cli/tui/attack_specs/specs/tfc.py +80 -0
  89. hackagent-0.12.0/hackagent/cli/tui/attack_specs/types.py +158 -0
  90. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/cli/tui/base.py +1 -1
  91. hackagent-0.12.0/hackagent/cli/tui/theme.py +187 -0
  92. hackagent-0.12.0/hackagent/cli/tui/views/attacks/__init__.py +37 -0
  93. hackagent-0.12.0/hackagent/cli/tui/views/attacks/executor.py +429 -0
  94. hackagent-0.12.0/hackagent/cli/tui/views/attacks/form.py +509 -0
  95. hackagent-0.12.0/hackagent/cli/tui/views/attacks/helpers.py +89 -0
  96. hackagent-0.12.0/hackagent/cli/tui/views/attacks/layout.py +263 -0
  97. hackagent-0.12.0/hackagent/cli/tui/views/attacks/runner.py +286 -0
  98. hackagent-0.12.0/hackagent/cli/tui/views/attacks/tab.py +390 -0
  99. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/cli/tui/views/config.py +2 -3
  100. hackagent-0.12.0/hackagent/cli/tui/views/results/__init__.py +58 -0
  101. hackagent-0.12.0/hackagent/cli/tui/views/results/details.py +377 -0
  102. hackagent-0.12.0/hackagent/cli/tui/views/results/export.py +173 -0
  103. hackagent-0.12.0/hackagent/cli/tui/views/results/formatters/__init__.py +54 -0
  104. hackagent-0.12.0/hackagent/cli/tui/views/results/formatters/datetimes.py +39 -0
  105. hackagent-0.12.0/hackagent/cli/tui/views/results/formatters/http.py +365 -0
  106. hackagent-0.12.0/hackagent/cli/tui/views/results/formatters/run_report.py +183 -0
  107. hackagent-0.12.0/hackagent/cli/tui/views/results/formatters/summaries.py +297 -0
  108. hackagent-0.12.0/hackagent/cli/tui/views/results/formatters/text.py +113 -0
  109. hackagent-0.12.0/hackagent/cli/tui/views/results/formatters/traces.py +351 -0
  110. hackagent-0.12.0/hackagent/cli/tui/views/results/tab.py +400 -0
  111. hackagent-0.12.0/hackagent/cli/tui/views/results/table.py +212 -0
  112. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/cli/tui/widgets/actions.py +4 -6
  113. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/cli/utils.py +4 -0
  114. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/config.py +58 -3
  115. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/datasets/__init__.py +4 -0
  116. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/datasets/presets.py +24 -2
  117. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/datasets/providers/__init__.py +2 -0
  118. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/datasets/providers/huggingface.py +23 -2
  119. hackagent-0.12.0/hackagent/datasets/providers/url_json.py +151 -0
  120. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/datasets/registry.py +131 -37
  121. hackagent-0.12.0/hackagent/examples/codex/README.md +118 -0
  122. hackagent-0.12.0/hackagent/examples/codex/hack_codex.py +89 -0
  123. hackagent-0.12.0/hackagent/examples/codex/hack_ollama.py +77 -0
  124. hackagent-0.12.0/hackagent/examples/hermes/README.md +97 -0
  125. hackagent-0.12.0/hackagent/examples/hermes/hack_hermes.py +94 -0
  126. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/examples/ollama/demo.py +24 -30
  127. hackagent-0.12.0/hackagent/examples/openai_sdk/db_tool_sandbox/README.md +70 -0
  128. hackagent-0.12.0/hackagent/examples/openai_sdk/db_tool_sandbox/agent.py +494 -0
  129. hackagent-0.12.0/hackagent/examples/openai_sdk/db_tool_sandbox/hack.py +101 -0
  130. hackagent-0.12.0/hackagent/examples/openai_sdk/db_tool_sandbox/sandbox.db +0 -0
  131. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/examples/openai_sdk/rag/README.md +7 -15
  132. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/examples/rag/test_indirect_injection.py +12 -14
  133. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/router/__init__.py +2 -0
  134. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/router/_chat_registration.py +2 -3
  135. hackagent-0.12.0/hackagent/router/providers/codex.py +633 -0
  136. hackagent-0.12.0/hackagent/router/providers/hermes.py +482 -0
  137. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/router/providers/web.py +39 -9
  138. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/router/router.py +4 -0
  139. hackagent-0.12.0/hackagent/router/tracking/audit.py +72 -0
  140. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/router/tracking/category_classifier.py +2 -1
  141. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/router/tracking/coordinator.py +42 -4
  142. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/router/tracking/decorators.py +25 -12
  143. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/router/tracking/step.py +36 -1
  144. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/router/tracking/tracker.py +79 -49
  145. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/router/types.py +15 -0
  146. hackagent-0.12.0/hackagent/server/dashboard/_attack_builder_mixin.py +558 -0
  147. hackagent-0.12.0/hackagent/server/dashboard/_builder_config.py +271 -0
  148. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/dashboard/_constants.py +0 -8
  149. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/dashboard/_data_mixin.py +2 -0
  150. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/dashboard/_layout_mixin.py +158 -144
  151. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/dashboard/_page.py +25 -4
  152. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/dashboard/_reports_mixin.py +30 -12
  153. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/dashboard/_result_detail_mixin.py +10 -1
  154. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/dashboard/_runs_mixin.py +7 -1
  155. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/dashboard/attack_cards/_advprefix.py +4 -13
  156. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/dashboard/attack_cards/_bon.py +4 -13
  157. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/dashboard/attack_cards/_generic.py +0 -56
  158. hackagent-0.12.0/hackagent/server/dashboard/attack_cards/_pair.py +284 -0
  159. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/dashboard/attack_cards/_pap.py +4 -13
  160. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/dashboard/attack_cards/_shared.py +117 -0
  161. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/dashboard/attack_cards/_static_template.py +4 -13
  162. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/storage/local.py +94 -1
  163. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/storage/remote.py +11 -14
  164. {hackagent-0.11.0 → hackagent-0.12.0}/pyproject.toml +17 -4
  165. hackagent-0.11.0/hackagent/attacks/techniques/bon/evaluation.py +0 -147
  166. hackagent-0.11.0/hackagent/attacks/techniques/cipherchat/evaluation.py +0 -97
  167. hackagent-0.11.0/hackagent/attacks/techniques/fc/evaluation.py +0 -181
  168. hackagent-0.11.0/hackagent/attacks/techniques/flipattack/evaluation.py +0 -223
  169. hackagent-0.11.0/hackagent/attacks/techniques/h4rm3l/evaluation.py +0 -174
  170. hackagent-0.11.0/hackagent/attacks/techniques/mml/evaluation.py +0 -220
  171. hackagent-0.11.0/hackagent/attacks/techniques/pair/evaluation.py +0 -90
  172. hackagent-0.11.0/hackagent/attacks/techniques/pap/evaluation.py +0 -69
  173. hackagent-0.11.0/hackagent/cli/commands/attack.py +0 -1293
  174. hackagent-0.11.0/hackagent/cli/tui/attack_specs.py +0 -1627
  175. hackagent-0.11.0/hackagent/cli/tui/views/attacks.py +0 -1431
  176. hackagent-0.11.0/hackagent/cli/tui/views/results.py +0 -2479
  177. hackagent-0.11.0/hackagent/server/dashboard/attack_cards/_pair.py +0 -194
  178. {hackagent-0.11.0 → hackagent-0.12.0}/LICENSE +0 -0
  179. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/__init__.py +0 -0
  180. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/__init__.py +0 -0
  181. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/evaluator/pattern_evaluators.py +0 -0
  182. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/generator/__init__.py +0 -0
  183. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/generator/templates.py +0 -0
  184. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/objectives/__init__.py +0 -0
  185. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/objectives/base.py +0 -0
  186. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/objectives/harmful_behavior.py +0 -0
  187. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/objectives/jailbreak.py +0 -0
  188. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/objectives/policy_violation.py +0 -0
  189. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/objectives/rag.py +0 -0
  190. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/registry.py +0 -0
  191. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/shared/__init__.py +0 -0
  192. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/shared/guardrail.py +0 -0
  193. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/shared/progress.py +0 -0
  194. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/shared/response_utils.py +0 -0
  195. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/shared/router_factory.py +0 -0
  196. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/shared/translation.py +0 -0
  197. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/shared/tui.py +0 -0
  198. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/shared/utils.py +0 -0
  199. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/__init__.py +0 -0
  200. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/advprefix/__init__.py +0 -0
  201. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/advprefix/completions.py +0 -0
  202. /hackagent-0.11.0/hackagent/attacks/techniques/advprefix/evaluation.py → /hackagent-0.12.0/hackagent/attacks/techniques/advprefix/eval_pipeline.py +0 -0
  203. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/advprefix/generate.py +0 -0
  204. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/advprefix/utils.py +0 -0
  205. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/autodan_turbo/__init__.py +0 -0
  206. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/autodan_turbo/dashboard_tracing.py +0 -0
  207. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/autodan_turbo/log_styles.py +0 -0
  208. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/autodan_turbo/strategy_library.py +0 -0
  209. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/autodan_turbo/summarizer.py +0 -0
  210. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/baseline/__init__.py +0 -0
  211. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/bon/__init__.py +0 -0
  212. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/bon/config.py +0 -0
  213. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/bon/generation.py +0 -0
  214. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/cipherchat/__init__.py +0 -0
  215. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/cipherchat/config.py +0 -0
  216. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/cipherchat/encode_experts.py +0 -0
  217. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/cipherchat/generation.py +0 -0
  218. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/cipherchat/prompts_and_demonstrations.py +0 -0
  219. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/fc/__init__.py +0 -0
  220. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/fc/config.py +0 -0
  221. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/fc/generation.py +0 -0
  222. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/fc/prompts.py +0 -0
  223. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/flipattack/__init__.py +0 -0
  224. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/flipattack/config.py +0 -0
  225. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/flipattack/generation.py +0 -0
  226. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/h4rm3l/__init__.py +0 -0
  227. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/h4rm3l/config.py +0 -0
  228. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/h4rm3l/decorators.py +0 -0
  229. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/h4rm3l/generation.py +0 -0
  230. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/mml/__init__.py +0 -0
  231. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/mml/config.py +0 -0
  232. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/mml/generation.py +0 -0
  233. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/mml/image_encoder.py +0 -0
  234. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/mml/prompts.py +0 -0
  235. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/pair/__init__.py +0 -0
  236. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/pap/__init__.py +0 -0
  237. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/pap/config.py +0 -0
  238. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/pap/generation.py +0 -0
  239. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/pap/taxonomy.py +0 -0
  240. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/rag/__init__.py +0 -0
  241. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/static_template/__init__.py +0 -0
  242. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/static_template/generation.py +0 -0
  243. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/tap/__init__.py +0 -0
  244. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/attacks/techniques/tap/config.py +0 -0
  245. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/cli/__init__.py +0 -0
  246. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/cli/commands/__init__.py +0 -0
  247. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/cli/commands/agent.py +0 -0
  248. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/cli/commands/claude.py +0 -0
  249. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/cli/commands/config.py +0 -0
  250. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/cli/commands/results.py +0 -0
  251. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/cli/commands/web.py +0 -0
  252. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/cli/config.py +0 -0
  253. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/cli/tui/__init__.py +0 -0
  254. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/cli/tui/events.py +0 -0
  255. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/cli/tui/logger.py +0 -0
  256. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/cli/tui/views/__init__.py +0 -0
  257. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/cli/tui/views/agents.py +0 -0
  258. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/cli/tui/widgets/__init__.py +0 -0
  259. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/cli/tui/widgets/clipboard.py +0 -0
  260. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/cli/tui/widgets/logs.py +0 -0
  261. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/datasets/base.py +0 -0
  262. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/datasets/intents.py +0 -0
  263. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/datasets/omnisafebench/dataset.json +0 -0
  264. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/datasets/providers/file.py +0 -0
  265. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/errors.py +0 -0
  266. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/examples/claude/README.md +0 -0
  267. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/examples/claude/hack_claude.py +0 -0
  268. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/examples/claude/hack_ollama.py +0 -0
  269. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/examples/google_adk/jailbreak_eval/__init__.py +0 -0
  270. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/examples/google_adk/jailbreak_eval/agent.py +0 -0
  271. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/examples/google_adk/jailbreak_eval/hack.py +0 -0
  272. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/examples/google_adk/multi_tool_agent/__init__.py +0 -0
  273. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/examples/google_adk/multi_tool_agent/agent.py +0 -0
  274. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/examples/google_adk/multi_tool_agent/hack.py +0 -0
  275. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/examples/langchain/rag/README.md +0 -0
  276. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/examples/langchain/rag/agent_client.py +0 -0
  277. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/examples/langchain/rag/agent_server.py +0 -0
  278. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/examples/langchain/rag/hack.py +0 -0
  279. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/examples/langchain/rag/ingest.py +0 -0
  280. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/examples/langchain/rag/policies.pdf +0 -0
  281. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/examples/langchain/rag/read_db.py +0 -0
  282. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/examples/litellm_multi_provider/README.md +0 -0
  283. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/examples/litellm_multi_provider/__init__.py +0 -0
  284. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/examples/litellm_multi_provider/demo.py +0 -0
  285. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/examples/ollama/hack.py +0 -0
  286. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/examples/ollama/local.py +0 -0
  287. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/examples/openai_sdk/multi_judge/README.md +0 -0
  288. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/examples/openai_sdk/multi_judge/run_flipattack_multi_judge.py +0 -0
  289. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/examples/openai_sdk/pc_tool_sandbox/README.md +0 -0
  290. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/examples/openai_sdk/pc_tool_sandbox/agent.py +0 -0
  291. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/examples/openai_sdk/pc_tool_sandbox/confidential/db_credentials.txt +0 -0
  292. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/examples/openai_sdk/pc_tool_sandbox/hack.py +0 -0
  293. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/examples/openai_sdk/quick_evaluation/README.md +0 -0
  294. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/examples/openai_sdk/quick_evaluation/run_h4rm3l.py +0 -0
  295. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/examples/openai_sdk/rag/agent_server.py +0 -0
  296. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/examples/openai_sdk/rag/hack.py +0 -0
  297. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/examples/openai_sdk/rag/ingest.py +0 -0
  298. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/examples/openai_sdk/rag/policies.pdf +0 -0
  299. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/examples/rag/.gitignore +0 -0
  300. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/examples/rag/test_data/gender_studies_overview.txt +0 -0
  301. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/examples/vllm/hack.py +0 -0
  302. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/examples/web/README.md +0 -0
  303. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/examples/web/hack.py +0 -0
  304. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/examples/web/plan.py +0 -0
  305. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/logger.py +0 -0
  306. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/__init__.py +0 -0
  307. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/base.py +0 -0
  308. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/craft_adversarial_data/__init__.py +0 -0
  309. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/craft_adversarial_data/profile.py +0 -0
  310. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/craft_adversarial_data/types.py +0 -0
  311. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/craft_adversarial_data/vulnerabilities.py +0 -0
  312. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/credential_exposure/__init__.py +0 -0
  313. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/credential_exposure/profile.py +0 -0
  314. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/credential_exposure/types.py +0 -0
  315. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/credential_exposure/vulnerabilities.py +0 -0
  316. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/excessive_agency/__init__.py +0 -0
  317. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/excessive_agency/profile.py +0 -0
  318. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/excessive_agency/types.py +0 -0
  319. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/excessive_agency/vulnerabilities.py +0 -0
  320. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/input_manipulation_attack/__init__.py +0 -0
  321. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/input_manipulation_attack/profile.py +0 -0
  322. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/input_manipulation_attack/types.py +0 -0
  323. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/input_manipulation_attack/vulnerabilities.py +0 -0
  324. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/jailbreak/__init__.py +0 -0
  325. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/jailbreak/profile.py +0 -0
  326. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/jailbreak/types.py +0 -0
  327. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/jailbreak/vulnerabilities.py +0 -0
  328. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/malicious_tool_invocation/__init__.py +0 -0
  329. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/malicious_tool_invocation/profile.py +0 -0
  330. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/malicious_tool_invocation/types.py +0 -0
  331. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/malicious_tool_invocation/vulnerabilities.py +0 -0
  332. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/misinformation/__init__.py +0 -0
  333. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/misinformation/profile.py +0 -0
  334. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/misinformation/types.py +0 -0
  335. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/misinformation/vulnerabilities.py +0 -0
  336. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/model_evasion/__init__.py +0 -0
  337. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/model_evasion/profile.py +0 -0
  338. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/model_evasion/types.py +0 -0
  339. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/model_evasion/vulnerabilities.py +0 -0
  340. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/profile_helpers.py +0 -0
  341. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/profile_types.py +0 -0
  342. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/prompt_injection/__init__.py +0 -0
  343. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/prompt_injection/profile.py +0 -0
  344. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/prompt_injection/templates.py +0 -0
  345. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/prompt_injection/types.py +0 -0
  346. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/prompt_injection/vulnerabilities.py +0 -0
  347. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/public_facing_application_exploitation/__init__.py +0 -0
  348. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/public_facing_application_exploitation/profile.py +0 -0
  349. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/public_facing_application_exploitation/types.py +0 -0
  350. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/public_facing_application_exploitation/vulnerabilities.py +0 -0
  351. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/registry.py +0 -0
  352. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/sensitive_information_disclosure/__init__.py +0 -0
  353. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/sensitive_information_disclosure/profile.py +0 -0
  354. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/sensitive_information_disclosure/types.py +0 -0
  355. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/sensitive_information_disclosure/vulnerabilities.py +0 -0
  356. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/system_prompt_leakage/__init__.py +0 -0
  357. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/system_prompt_leakage/profile.py +0 -0
  358. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/system_prompt_leakage/types.py +0 -0
  359. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/system_prompt_leakage/vulnerabilities.py +0 -0
  360. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/utils.py +0 -0
  361. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/vector_embedding_weaknesses_exploit/__init__.py +0 -0
  362. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/vector_embedding_weaknesses_exploit/profile.py +0 -0
  363. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/vector_embedding_weaknesses_exploit/types.py +0 -0
  364. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/risks/vector_embedding_weaknesses_exploit/vulnerabilities.py +0 -0
  365. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/router/agent.py +0 -0
  366. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/router/discovery/__init__.py +0 -0
  367. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/router/discovery/browser.py +0 -0
  368. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/router/discovery/scanner.py +0 -0
  369. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/router/envelope.py +0 -0
  370. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/router/provider_config.py +0 -0
  371. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/router/providers/__init__.py +0 -0
  372. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/router/providers/adk.py +0 -0
  373. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/router/providers/claude.py +0 -0
  374. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/router/tracking/__init__.py +0 -0
  375. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/router/tracking/context.py +0 -0
  376. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/router/tracking/utils.py +0 -0
  377. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/router/tracking_logger.py +0 -0
  378. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/__init__.py +0 -0
  379. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/__init__.py +0 -0
  380. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/agent/__init__.py +0 -0
  381. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/agent/agent_create.py +0 -0
  382. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/agent/agent_destroy.py +0 -0
  383. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/agent/agent_list.py +0 -0
  384. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/agent/agent_partial_update.py +0 -0
  385. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/agent/agent_retrieve.py +0 -0
  386. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/agent/agent_update.py +0 -0
  387. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/apilogs/__init__.py +0 -0
  388. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/apilogs/apilogs_list.py +0 -0
  389. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/apilogs/apilogs_retrieve.py +0 -0
  390. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/apilogs/apilogs_summary_retrieve.py +0 -0
  391. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/attack/__init__.py +0 -0
  392. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/attack/attack_create.py +0 -0
  393. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/attack/attack_destroy.py +0 -0
  394. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/attack/attack_list.py +0 -0
  395. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/attack/attack_partial_update.py +0 -0
  396. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/attack/attack_retrieve.py +0 -0
  397. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/attack/attack_update.py +0 -0
  398. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/checkout/__init__.py +0 -0
  399. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/checkout/checkout_create.py +0 -0
  400. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/generate/__init__.py +0 -0
  401. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/generate/v1_chat_completions_create.py +0 -0
  402. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/judge/__init__.py +0 -0
  403. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/judge/judge_create.py +0 -0
  404. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/key/__init__.py +0 -0
  405. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/key/key_context_retrieve.py +0 -0
  406. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/key/key_create.py +0 -0
  407. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/key/key_destroy.py +0 -0
  408. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/key/key_list.py +0 -0
  409. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/key/key_retrieve.py +0 -0
  410. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/models.py +0 -0
  411. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/organization/__init__.py +0 -0
  412. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/organization/organization_create.py +0 -0
  413. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/organization/organization_destroy.py +0 -0
  414. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/organization/organization_list.py +0 -0
  415. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/organization/organization_me_retrieve.py +0 -0
  416. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/organization/organization_partial_update.py +0 -0
  417. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/organization/organization_retrieve.py +0 -0
  418. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/organization/organization_update.py +0 -0
  419. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/result/__init__.py +0 -0
  420. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/result/result_create.py +0 -0
  421. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/result/result_destroy.py +0 -0
  422. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/result/result_list.py +0 -0
  423. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/result/result_partial_update.py +0 -0
  424. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/result/result_retrieve.py +0 -0
  425. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/result/result_trace_create.py +0 -0
  426. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/result/result_update.py +0 -0
  427. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/run/__init__.py +0 -0
  428. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/run/run_create.py +0 -0
  429. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/run/run_destroy.py +0 -0
  430. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/run/run_list.py +0 -0
  431. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/run/run_partial_update.py +0 -0
  432. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/run/run_result_create.py +0 -0
  433. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/run/run_retrieve.py +0 -0
  434. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/run/run_run_tests_create.py +0 -0
  435. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/run/run_update.py +0 -0
  436. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/scripts/generate.py +0 -0
  437. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/scripts/generate.sh +0 -0
  438. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/scripts/openapi-python-client.yaml +0 -0
  439. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/user/__init__.py +0 -0
  440. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/user/user_create.py +0 -0
  441. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/user/user_destroy.py +0 -0
  442. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/user/user_list.py +0 -0
  443. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/user/user_me_retrieve.py +0 -0
  444. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/user/user_me_update.py +0 -0
  445. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/user/user_partial_update.py +0 -0
  446. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/user/user_retrieve.py +0 -0
  447. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/api/user/user_update.py +0 -0
  448. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/client.py +0 -0
  449. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/dashboard/__init__.py +0 -0
  450. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/dashboard/_analysis_data_mixin.py +0 -0
  451. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/dashboard/_api.py +0 -0
  452. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/dashboard/_components.py +0 -0
  453. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/dashboard/_helpers.py +0 -0
  454. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/dashboard/_run_history_results_mixin.py +0 -0
  455. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/dashboard/_run_results_mixin.py +0 -0
  456. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/dashboard/_tap_trace_mixin.py +0 -0
  457. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/dashboard/_trace_analysis_mixin.py +0 -0
  458. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/dashboard/_trace_render_mixin.py +0 -0
  459. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/dashboard/app.py +0 -0
  460. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/dashboard/attack_cards/__init__.py +0 -0
  461. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/dashboard/attack_cards/_autodan.py +0 -0
  462. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/dashboard/attack_cards/_fc.py +0 -0
  463. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/dashboard/attack_cards/_mml.py +0 -0
  464. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/dashboard/attack_cards/_tap.py +0 -0
  465. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/dashboard/attack_cards/_tfc.py +0 -0
  466. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/dashboard/templates/index.html +0 -0
  467. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/errors.py +0 -0
  468. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/storage/__init__.py +0 -0
  469. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/storage/base.py +0 -0
  470. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/storage/enums.py +0 -0
  471. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/server/types.py +0 -0
  472. {hackagent-0.11.0 → hackagent-0.12.0}/hackagent/utils.py +0 -0
@@ -7,6 +7,7 @@ reports/
7
7
  slurm/
8
8
  tools/
9
9
  docs/docs/attacks/walkthroughs/
10
+ .worktrees/
10
11
 
11
12
  # Editors
12
13
  .vscode/
@@ -54,6 +55,8 @@ MANIFEST
54
55
  # before PyInstaller builds the exe, so as to inject date/other infos into it.
55
56
  *.manifest
56
57
  *.spec
58
+ # The release build spec is checked in, unlike generated ones.
59
+ !packaging/hackagent.spec
57
60
 
58
61
  # Installer logs
59
62
  pip-log.txt
@@ -139,3 +142,6 @@ dmypy.json
139
142
  tests/e2e/attacks/
140
143
 
141
144
  .tmp
145
+
146
+ # pytest-textual-snapshot report artifact
147
+ snapshot_report.html
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hackagent
3
- Version: 0.11.0
3
+ Version: 0.12.0
4
4
  Summary: HackAgent is an open-source security toolkit to detect vulnerabilities of your AI Agents.
5
5
  Author-email: AI Security Lab <ais@ai4i.it>
6
6
  License: Apache-2.0
@@ -18,6 +18,7 @@ Requires-Python: >=3.10
18
18
  Requires-Dist: click>=8.1.0
19
19
  Requires-Dist: datasets>=2.14.0
20
20
  Requires-Dist: faiss-cpu>=1.13.2
21
+ Requires-Dist: flask>=3.1.2
21
22
  Requires-Dist: httpx>=0.27.0
22
23
  Requires-Dist: litellm>=1.69.2
23
24
  Requires-Dist: nicegui>=2.0
@@ -91,6 +92,27 @@ pip install hackagent
91
92
 
92
93
  No API key required: HackAgent works locally out of the box.
93
94
 
95
+ ### Standalone binary (no Python required)
96
+
97
+ Every [GitHub Release](https://github.com/AISecurityLab/hackagent/releases) ships a
98
+ self-contained archive per platform:
99
+
100
+ | Platform | Asset |
101
+ |----------|-------|
102
+ | Linux x86_64 | `hackagent-<version>-linux-x86_64.tar.gz` |
103
+ | macOS arm64 | `hackagent-<version>-macos-arm64.tar.gz` |
104
+ | macOS x86_64 | `hackagent-<version>-macos-x86_64.tar.gz` |
105
+ | Windows x86_64 | `hackagent-<version>-windows-x86_64.zip` |
106
+
107
+ Extract the archive and run the `hackagent` launcher inside it — no Python, `pip`
108
+ or `uv` install needed. Keep the extracted folder intact; the launcher loads the
109
+ libraries next to it.
110
+
111
+ > **Note:** the `WEB` provider drives a real browser through Playwright, whose
112
+ > browser binaries cannot be embedded in the archive (or in the PyPI package).
113
+ > Before using `hackagent web`-based targets, install them once with
114
+ > `playwright install`.
115
+
94
116
 
95
117
  Questions? Join [community discussions](https://github.com/AISecurityLab/hackagent/discussions) or email ais@ai4i.it.
96
118
 
@@ -104,7 +126,7 @@ HackAgent uses a modular pipeline to test agent robustness end-to-end.
104
126
  | **Generator** | LLM role that creates adversarial prompts to test the target agent |
105
127
  | **Judge** | LLM role that evaluates whether attacks bypass safety measures |
106
128
  | **Target Agent** | Your AI agent under test across supported frameworks |
107
- | **Datasets** | Pre-built benchmark presets plus custom HuggingFace/file datasets |
129
+ | **Datasets** | Pre-built benchmark presets plus custom HuggingFace/file/URL JSON datasets |
108
130
 
109
131
  ## Supported Frameworks
110
132
 
@@ -58,6 +58,27 @@ pip install hackagent
58
58
 
59
59
  No API key required: HackAgent works locally out of the box.
60
60
 
61
+ ### Standalone binary (no Python required)
62
+
63
+ Every [GitHub Release](https://github.com/AISecurityLab/hackagent/releases) ships a
64
+ self-contained archive per platform:
65
+
66
+ | Platform | Asset |
67
+ |----------|-------|
68
+ | Linux x86_64 | `hackagent-<version>-linux-x86_64.tar.gz` |
69
+ | macOS arm64 | `hackagent-<version>-macos-arm64.tar.gz` |
70
+ | macOS x86_64 | `hackagent-<version>-macos-x86_64.tar.gz` |
71
+ | Windows x86_64 | `hackagent-<version>-windows-x86_64.zip` |
72
+
73
+ Extract the archive and run the `hackagent` launcher inside it — no Python, `pip`
74
+ or `uv` install needed. Keep the extracted folder intact; the launcher loads the
75
+ libraries next to it.
76
+
77
+ > **Note:** the `WEB` provider drives a real browser through Playwright, whose
78
+ > browser binaries cannot be embedded in the archive (or in the PyPI package).
79
+ > Before using `hackagent web`-based targets, install them once with
80
+ > `playwright install`.
81
+
61
82
 
62
83
  Questions? Join [community discussions](https://github.com/AISecurityLab/hackagent/discussions) or email ais@ai4i.it.
63
84
 
@@ -71,7 +92,7 @@ HackAgent uses a modular pipeline to test agent robustness end-to-end.
71
92
  | **Generator** | LLM role that creates adversarial prompts to test the target agent |
72
93
  | **Judge** | LLM role that evaluates whether attacks bypass safety measures |
73
94
  | **Target Agent** | Your AI agent under test across supported frameworks |
74
- | **Datasets** | Pre-built benchmark presets plus custom HuggingFace/file datasets |
95
+ | **Datasets** | Pre-built benchmark presets plus custom HuggingFace/file/URL JSON datasets |
75
96
 
76
97
  ## Supported Frameworks
77
98
 
@@ -0,0 +1,21 @@
1
+ # Copyright 2026 - AI4I. All rights reserved.
2
+ # SPDX-License-Identifier: Apache-2.0
3
+
4
+ """Version lookup that also works from a frozen (PyInstaller) binary."""
5
+
6
+ import os
7
+ from importlib.metadata import PackageNotFoundError, version as _distribution_version
8
+
9
+ UNKNOWN_VERSION = "unknown"
10
+
11
+
12
+ def get_version() -> str:
13
+ """Return the installed ``hackagent`` version.
14
+
15
+ Frozen builds may ship without distribution metadata, so fall back to the
16
+ ``HACKAGENT_BUILD_VERSION`` value baked in at packaging time.
17
+ """
18
+ try:
19
+ return _distribution_version("hackagent")
20
+ except PackageNotFoundError:
21
+ return os.environ.get("HACKAGENT_BUILD_VERSION") or UNKNOWN_VERSION
@@ -62,13 +62,14 @@ class HackAgent:
62
62
  base_url: Optional[str] = None,
63
63
  api_key: Optional[str] = None,
64
64
  raise_on_unexpected_status: bool = False,
65
- timeout: Optional[float] = None,
65
+ timeout: Optional[float] = 120.0,
66
66
  metadata: Optional[Dict[str, Any]] = None,
67
67
  target_config: Optional[Dict[str, Any]] = None,
68
68
  adapter_operational_config: Optional[Dict[str, Any]] = None,
69
69
  thinking: Optional[bool] = None,
70
70
  before_guardrail: Optional[Dict[str, Any]] = None,
71
71
  after_guardrail: Optional[Dict[str, Any]] = None,
72
+ backend: Optional[Any] = None,
72
73
  ):
73
74
  """
74
75
  Initializes the HackAgent client and prepares it for interaction.
@@ -95,8 +96,11 @@ class HackAgent:
95
96
  raise an exception for any HTTP status codes that are not typically
96
97
  expected for a successful operation. Defaults to `False`.
97
98
  timeout: The timeout duration in seconds for API requests made by the
98
- authenticated client. Defaults to `None` (which might mean a
99
- default timeout from the underlying HTTP library is used).
99
+ authenticated (remote) HackAgent backend client. Defaults to
100
+ `120.0` seconds so requests to a misbehaving/unreachable backend
101
+ fail predictably instead of hanging indefinitely. Pass `None`
102
+ explicitly to opt out and disable the timeout (unbounded wait,
103
+ the previous default behavior).
100
104
  metadata: Optional dictionary containing agent-specific metadata.
101
105
  target_config: Optional default request settings for the configured
102
106
  victim model. This is the preferred place to define target-side
@@ -107,11 +111,21 @@ class HackAgent:
107
111
  When set to `False`, requests sent through the target OLLAMA adapter
108
112
  include `think: false` to disable thinking output. Ignored for
109
113
  non-OLLAMA target agent types.
114
+ backend: Optional pre-built ``StorageBackend`` to persist runs and
115
+ results through. When omitted, a backend is selected from the
116
+ resolved API key (remote) or a default local SQLite database.
117
+ Supplying one lets an embedding host — e.g. the local dashboard
118
+ — reuse its own already-open backend.
110
119
  """
111
120
 
112
121
  resolved_auth_token = utils.resolve_api_token(direct_api_key_param=api_key)
113
122
 
114
- if resolved_auth_token:
123
+ if backend is not None:
124
+ self.backend = backend
125
+ logger.info(
126
+ "HackAgent using caller-provided backend %s", type(backend).__name__
127
+ )
128
+ elif resolved_auth_token:
115
129
  from hackagent.server.client import AuthenticatedClient
116
130
  from hackagent.server.storage.remote import RemoteBackend
117
131
 
@@ -320,3 +334,231 @@ class HackAgent:
320
334
  raise HackAgentError(
321
335
  f"An unexpected error occurred during attack: {e}"
322
336
  ) from e
337
+
338
+ def hack_chain(
339
+ self,
340
+ attacks: Optional[list] = None,
341
+ goals: Optional[list] = None,
342
+ run_config_override: Optional[Dict[str, Any]] = None,
343
+ fail_on_run_error: bool = True,
344
+ escalate_only_mitigated: bool = True,
345
+ _tui_event_bus: Optional[Any] = None,
346
+ ) -> list:
347
+ """
348
+ Runs a sequence of attack strategies against a shared pool of goals.
349
+
350
+ By default (``escalate_only_mitigated=True``) this implements a
351
+ "fallback ladder": every goal starts at ``attacks[0]``. Any goal for
352
+ which the victim's response is judged successful (a jailbreak/
353
+ violation) is considered resolved and is dropped from the chain — it
354
+ is never retried. Any goal that is mitigated (the victim's response
355
+ is judged safe) is carried over and retried with ``attacks[1]``, then
356
+ ``attacks[2]``, and so on, until either the goal succeeds or the
357
+ chain is exhausted.
358
+
359
+ With ``escalate_only_mitigated=False``, every goal is instead sent to
360
+ *every* attack in the chain regardless of outcome — useful for
361
+ running several attacks against the same goal set and collecting all
362
+ of their results in one call, rather than escalating only failures.
363
+
364
+ Success/mitigation is determined per goal from the evaluated result
365
+ rows returned by each step (see
366
+ ``hackagent.attacks.evaluator.metrics.is_successful_result``): a goal
367
+ is considered successful for a step if *any* of its result rows for
368
+ that step are judged successful.
369
+
370
+ Args:
371
+ attacks: Ordered list of ``attack_config`` dicts, one per chain
372
+ step, using the same shape accepted by :meth:`hack` (each
373
+ must include its own ``attack_type`` and any attack-specific
374
+ settings). Only the *first* entry needs to specify how goals
375
+ are sourced (``goals``, ``dataset`` or ``intents``) unless
376
+ the ``goals`` parameter below is provided; subsequent steps
377
+ automatically receive only the goals still mitigated by the
378
+ previous step (or all goals, see ``escalate_only_mitigated``).
379
+ Defaults to ``None``, which resolves to the Jailbreak
380
+ evaluation campaign's primary attacks, in order — ``h4rm3l``
381
+ → ``TAP`` → ``PAIR`` (see
382
+ ``hackagent.risks.jailbreak.JAILBREAK_PROFILE``). A goal
383
+ source is still required either way, via ``goals`` or a
384
+ ``dataset``/``goals``/``intents`` key on the first step.
385
+ goals: Optional explicit list of goal strings to use for the
386
+ whole chain. When provided, it takes precedence over any
387
+ ``goals``/``dataset``/``intents`` set on ``attacks[0]``.
388
+ run_config_override: Optional run configuration overrides applied
389
+ to every step, forwarded to :meth:`hack`.
390
+ fail_on_run_error: Forwarded to :meth:`hack` for every step.
391
+ escalate_only_mitigated: When ``True`` (default), a goal only
392
+ moves on to the next attack if it was mitigated at the
393
+ current step — goals that already succeeded are dropped, and
394
+ each goal's final result is either its first success or its
395
+ last (final) attempt. When ``False``, every goal is sent to
396
+ every attack regardless of outcome, and results from *all*
397
+ steps are kept for every goal (nothing is dropped or
398
+ overwritten).
399
+
400
+ Returns:
401
+ A flat list of result rows (same row shape as :meth:`hack`),
402
+ grouped by original goal, in first-seen order. Each row is
403
+ tagged with ``chain_step`` (0-based index into ``attacks``) and
404
+ ``chain_attack_type`` identifying which attack produced it.
405
+
406
+ Raises:
407
+ HackAgentError: If ``attacks`` is empty, or a step is missing
408
+ ``attack_type``.
409
+ """
410
+ if attacks is None:
411
+ # Default chain: the Jailbreak evaluation campaign's primary
412
+ # attacks, in campaign order. `technique` strings in the profile
413
+ # (e.g. "TAP", "PAIR") use display casing; `attack_strategies`
414
+ # keys are lowercase, so normalize before use.
415
+ from hackagent.risks.jailbreak import JAILBREAK_PROFILE
416
+
417
+ attacks = [
418
+ {"attack_type": rec.technique.strip().lower()}
419
+ for rec in JAILBREAK_PROFILE.primary_attacks
420
+ ]
421
+
422
+ if not attacks:
423
+ raise HackAgentError(
424
+ "'attacks' must be a non-empty list of attack_config dicts."
425
+ )
426
+
427
+ from hackagent.attacks.evaluator.metrics import is_successful_result
428
+
429
+ n_steps = len(attacks)
430
+ remaining_goals: Optional[list] = list(goals) if goals is not None else None
431
+ goal_order: list = list(goals) if goals is not None else []
432
+ final_rows_by_goal: Dict[str, list] = {}
433
+
434
+ for step_index, step_config in enumerate(attacks):
435
+ if remaining_goals is not None and not remaining_goals:
436
+ logger.info(
437
+ "All goals resolved before chain step %d/%d; skipping remaining attack(s).",
438
+ step_index + 1,
439
+ n_steps,
440
+ )
441
+ break
442
+
443
+ attack_type = step_config.get("attack_type")
444
+ if not attack_type:
445
+ raise HackAgentError(
446
+ f"hack_chain step {step_index} is missing 'attack_type'."
447
+ )
448
+
449
+ step_attack_config = dict(step_config)
450
+ if remaining_goals is not None:
451
+ step_attack_config["goals"] = remaining_goals
452
+ step_attack_config.pop("dataset", None)
453
+ step_attack_config.pop("intents", None)
454
+
455
+ logger.info(
456
+ "hack_chain step %d/%d: running '%s' against %s goal(s)",
457
+ step_index + 1,
458
+ n_steps,
459
+ attack_type,
460
+ len(remaining_goals) if remaining_goals is not None else "all",
461
+ )
462
+
463
+ # Each step is executed through the same public `hack()` entry
464
+ # point used everywhere else (CLI/TUI/SDK) — hack_chain adds no
465
+ # parallel execution path, it only decides *which* goals each
466
+ # step receives and tags/regroups the returned rows afterwards.
467
+ step_results = self.hack(
468
+ attack_config=step_attack_config,
469
+ run_config_override=run_config_override,
470
+ fail_on_run_error=fail_on_run_error,
471
+ _tui_event_bus=_tui_event_bus,
472
+ )
473
+ step_rows = (
474
+ step_results
475
+ if isinstance(step_results, list)
476
+ else list(step_results or [])
477
+ )
478
+
479
+ # Group returned rows by their `goal` text — the same lookup
480
+ # convention used throughout the codebase to associate a result
481
+ # back to its goal (e.g. Tracker.get_goal_context_by_goal,
482
+ # TrackingCoordinator, BaseEvaluationStep's MERGE_KEYS). Every
483
+ # technique preserves the original goal string verbatim in its
484
+ # output rows, so this is a plain, reliable lookup — no need to
485
+ # reconstruct or second-guess it.
486
+ #
487
+ # Grouping (rather than checking each row independently) matters
488
+ # because a single goal can have several rows in one step — not
489
+ # from multiple judges (those are already merged into per-judge
490
+ # columns, e.g. eval_hb/eval_jb, on the *same* row, with the
491
+ # majority vote across them resolved by is_successful_result()
492
+ # before we ever see it here) but from multiple distinct attempts
493
+ # at the same goal (e.g. AdvPrefix's several generated prefixes,
494
+ # BoN's N augmented variants, TAP/PAIR's tree branches), each its
495
+ # own (goal, prefix, completion) row. "Mitigated" means *all* of
496
+ # that goal's attempts failed; "succeeded" means *any* attempt
497
+ # did. A flat `for row in step_rows: if not successful: ...`
498
+ # can't express that OR-across-attempts semantics, and would
499
+ # also append the same goal multiple times (once per failing
500
+ # row) without an explicit dedup step.
501
+ rows_by_goal: Dict[str, list] = {}
502
+ for row in step_rows:
503
+ if not isinstance(row, dict):
504
+ continue
505
+ row_goal = row.get("goal", "unknown")
506
+ rows_by_goal.setdefault(row_goal, []).append(
507
+ {**row, "chain_step": step_index, "chain_attack_type": attack_type}
508
+ )
509
+
510
+ if remaining_goals is None:
511
+ # First step resolved its own goals internally (via 'goals',
512
+ # 'dataset' or 'intents' on attacks[0]) — dict insertion
513
+ # order already matches first-seen order, so reuse it
514
+ # directly instead of tracking a parallel order list.
515
+ remaining_goals = list(rows_by_goal.keys())
516
+ goal_order = list(remaining_goals)
517
+
518
+ next_remaining: list = []
519
+ # Iterate the goals we *sent* this step (`remaining_goals`), not
520
+ # `rows_by_goal`/`step_rows` directly: a goal that comes back
521
+ # with zero rows (e.g. the attack errored on it) must still be
522
+ # looked up here — `rows_by_goal.get(goal, [])` defaults to `[]`,
523
+ # and `not any([])` correctly keeps it mitigated/in-chain. If we
524
+ # only walked what actually came back in `step_rows`, a goal
525
+ # with no response would simply never appear and would silently
526
+ # fall out of the chain, as if it had succeeded.
527
+ for goal in remaining_goals:
528
+ goal_rows = rows_by_goal.get(goal, [])
529
+
530
+ if not escalate_only_mitigated:
531
+ # Every goal proceeds to every attack regardless of
532
+ # outcome; keep rows from all steps instead of only the
533
+ # latest attempt.
534
+ final_rows_by_goal.setdefault(goal, []).extend(goal_rows)
535
+ next_remaining.append(goal)
536
+ continue
537
+
538
+ if goal_rows:
539
+ final_rows_by_goal[goal] = goal_rows
540
+ mitigated = not any(is_successful_result(row) for row in goal_rows)
541
+ if mitigated:
542
+ next_remaining.append(goal)
543
+ else:
544
+ logger.info(
545
+ "Goal succeeded at chain step %d ('%s'); dropped from chain: %s",
546
+ step_index + 1,
547
+ attack_type,
548
+ str(goal)[:80],
549
+ )
550
+
551
+ remaining_goals = next_remaining
552
+
553
+ if remaining_goals and escalate_only_mitigated:
554
+ logger.info(
555
+ "%d goal(s) mitigated through the entire chain (%d step(s)): %s",
556
+ len(remaining_goals),
557
+ n_steps,
558
+ ", ".join(str(g)[:60] for g in remaining_goals),
559
+ )
560
+
561
+ final_results: list = []
562
+ for goal in goal_order:
563
+ final_results.extend(final_rows_by_goal.get(goal, []))
564
+ return final_results
@@ -2,7 +2,9 @@
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
 
4
4
  import abc
5
- from typing import Any, Dict
5
+ from typing import Any, Dict, List
6
+
7
+ from hackagent.attacks.types import AttackResult
6
8
 
7
9
 
8
10
  class BaseAttack(abc.ABC):
@@ -64,7 +66,7 @@ class BaseAttack(abc.ABC):
64
66
  pass
65
67
 
66
68
  @abc.abstractmethod
67
- def run(self, **kwargs: Any) -> Any:
69
+ def run(self, **kwargs: Any) -> List[AttackResult]:
68
70
  """
69
71
  Executes the attack logic.
70
72
 
@@ -80,12 +82,7 @@ class BaseAttack(abc.ABC):
80
82
  - target_model: The model to attack
81
83
 
82
84
  Returns:
83
- Attack-specific results. The format varies by implementation but
84
- typically includes:
85
- - adversarial_examples: Generated adversarial inputs
86
- - success_metrics: Attack success rates and statistics
87
- - detailed_results: Comprehensive result data (e.g., pandas DataFrame)
88
- - attack_report: Summary of attack performance
85
+ A list of :class:`~hackagent.attacks.types.AttackResult` instances.
89
86
 
90
87
  Raises:
91
88
  NotImplementedError: If the method is not implemented by a subclass.
@@ -38,6 +38,7 @@ Usage:
38
38
  calculate_majority_vote_asr,
39
39
  calculate_fleiss_kappa,
40
40
  calculate_per_judge_strictness,
41
+ is_successful_result,
41
42
  # Server sync
42
43
  sync_evaluation_to_server,
43
44
  update_single_result,
@@ -53,6 +54,7 @@ from hackagent.attacks.evaluator.judge_evaluators import (
53
54
  JailbreakBenchEvaluator,
54
55
  NuancedEvaluator,
55
56
  OnTopicEvaluator,
57
+ ScorerEvaluator,
56
58
  )
57
59
  from hackagent.attacks.evaluator.metrics import (
58
60
  calculate_confidence_score,
@@ -60,6 +62,7 @@ from hackagent.attacks.evaluator.metrics import (
60
62
  calculate_success_rate,
61
63
  generate_summary_report,
62
64
  group_by_goal,
65
+ is_successful_result,
63
66
  calculate_majority_vote_asr,
64
67
  calculate_fleiss_kappa,
65
68
  calculate_per_judge_strictness,
@@ -85,6 +88,7 @@ __all__ = [
85
88
  "HarmBenchEvaluator",
86
89
  "HarmBenchVariantEvaluator",
87
90
  "OnTopicEvaluator",
91
+ "ScorerEvaluator",
88
92
  "EVALUATOR_MAP",
89
93
  # Pattern evaluators
90
94
  "PatternEvaluator",
@@ -96,6 +100,7 @@ __all__ = [
96
100
  "calculate_per_goal_metrics",
97
101
  "generate_summary_report",
98
102
  "group_by_goal",
103
+ "is_successful_result",
99
104
  "calculate_majority_vote_asr",
100
105
  "calculate_fleiss_kappa",
101
106
  "calculate_per_judge_strictness",
@@ -186,6 +186,19 @@ class BaseJudgeEvaluator(ABC):
186
186
  f"Registration key: {self.agent_registration_key}"
187
187
  )
188
188
 
189
+ def _build_messages(self, user_content: str) -> List[Dict[str, str]]:
190
+ """Build the judge chat messages, honouring a user-defined system prompt.
191
+
192
+ ``EvaluatorConfig.system_prompt`` lets users prepend their own system
193
+ message (e.g. a custom rubric or persona) to every judge request.
194
+ """
195
+ messages: List[Dict[str, str]] = []
196
+ system_prompt = getattr(self.config, "system_prompt", None)
197
+ if isinstance(system_prompt, str) and system_prompt.strip():
198
+ messages.append({"role": "system", "content": system_prompt.strip()})
199
+ messages.append({"role": "user", "content": user_content})
200
+ return messages
201
+
189
202
  def _verify_keys(self, data: list[dict], required_keys: list) -> None:
190
203
  """Verify that all required keys exist in each dict."""
191
204
  if not data:
@@ -853,7 +866,7 @@ Answer (yes or no):"""
853
866
  )
854
867
 
855
868
  return {
856
- "messages": [{"role": "user", "content": feedback_prompt}],
869
+ "messages": self._build_messages(feedback_prompt),
857
870
  "max_tokens": self.config.max_tokens_eval,
858
871
  "temperature": 0.0, # Deterministic for retry
859
872
  }