hackagent 0.2.1__tar.gz → 0.2.3__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 (168) hide show
  1. {hackagent-0.2.1 → hackagent-0.2.3}/PKG-INFO +1 -1
  2. hackagent-0.2.3/hackagent/agent.py +212 -0
  3. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/api/agent/agent_destroy.py +1 -3
  4. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/api/agent/agent_partial_update.py +1 -3
  5. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/api/agent/agent_retrieve.py +1 -3
  6. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/api/agent/agent_update.py +1 -3
  7. hackagent-0.2.3/hackagent/api/apilogs/apilogs_list.py +158 -0
  8. hackagent-0.2.3/hackagent/api/apilogs/apilogs_retrieve.py +150 -0
  9. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/api/attack/attack_destroy.py +1 -3
  10. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/api/attack/attack_partial_update.py +1 -3
  11. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/api/attack/attack_retrieve.py +1 -3
  12. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/api/attack/attack_update.py +1 -3
  13. hackagent-0.2.3/hackagent/api/checkout/checkout_create.py +228 -0
  14. hackagent-0.2.3/hackagent/api/generate/generate_create.py +244 -0
  15. hackagent-0.2.3/hackagent/api/judge/judge_create.py +244 -0
  16. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/api/key/key_destroy.py +1 -3
  17. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/api/key/key_retrieve.py +1 -3
  18. hackagent-0.2.3/hackagent/api/organization/organization_create.py +199 -0
  19. hackagent-0.2.3/hackagent/api/organization/organization_destroy.py +98 -0
  20. hackagent-0.2.3/hackagent/api/organization/organization_list.py +158 -0
  21. hackagent-0.2.3/hackagent/api/organization/organization_me_retrieve.py +126 -0
  22. hackagent-0.2.3/hackagent/api/organization/organization_partial_update.py +213 -0
  23. hackagent-0.2.3/hackagent/api/organization/organization_retrieve.py +151 -0
  24. hackagent-0.2.3/hackagent/api/organization/organization_update.py +213 -0
  25. hackagent-0.2.3/hackagent/api/prompt/__init__.py +1 -0
  26. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/api/prompt/prompt_destroy.py +1 -3
  27. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/api/prompt/prompt_partial_update.py +1 -3
  28. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/api/prompt/prompt_retrieve.py +1 -3
  29. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/api/prompt/prompt_update.py +1 -3
  30. hackagent-0.2.3/hackagent/api/result/__init__.py +1 -0
  31. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/api/result/result_destroy.py +1 -3
  32. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/api/result/result_partial_update.py +1 -3
  33. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/api/result/result_retrieve.py +1 -3
  34. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/api/result/result_trace_create.py +1 -3
  35. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/api/result/result_update.py +1 -3
  36. hackagent-0.2.3/hackagent/api/run/__init__.py +1 -0
  37. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/api/run/run_destroy.py +1 -3
  38. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/api/run/run_list.py +15 -0
  39. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/api/run/run_partial_update.py +1 -3
  40. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/api/run/run_result_create.py +1 -3
  41. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/api/run/run_retrieve.py +1 -3
  42. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/api/run/run_update.py +1 -3
  43. hackagent-0.2.3/hackagent/api/user/__init__.py +1 -0
  44. hackagent-0.2.3/hackagent/api/user/user_create.py +203 -0
  45. hackagent-0.2.3/hackagent/api/user/user_destroy.py +100 -0
  46. hackagent-0.2.3/hackagent/api/user/user_list.py +162 -0
  47. hackagent-0.2.3/hackagent/api/user/user_me_retrieve.py +126 -0
  48. hackagent-0.2.3/hackagent/api/user/user_me_update.py +199 -0
  49. hackagent-0.2.3/hackagent/api/user/user_partial_update.py +217 -0
  50. hackagent-0.2.3/hackagent/api/user/user_retrieve.py +155 -0
  51. hackagent-0.2.3/hackagent/api/user/user_update.py +217 -0
  52. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/attacks/AdvPrefix/config.py +1 -1
  53. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/attacks/AdvPrefix/generate.py +1 -1
  54. hackagent-0.2.3/hackagent/client.py +412 -0
  55. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/errors.py +14 -0
  56. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/logger.py +15 -0
  57. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/models/__init__.py +34 -0
  58. hackagent-0.2.3/hackagent/models/api_token_log.py +184 -0
  59. hackagent-0.2.3/hackagent/models/checkout_session_request_request.py +78 -0
  60. hackagent-0.2.3/hackagent/models/checkout_session_response.py +59 -0
  61. hackagent-0.2.3/hackagent/models/generate_error_response.py +59 -0
  62. hackagent-0.2.3/hackagent/models/generate_request_request.py +135 -0
  63. hackagent-0.2.3/hackagent/models/generate_request_request_messages_item.py +44 -0
  64. hackagent-0.2.3/hackagent/models/generate_success_response.py +59 -0
  65. hackagent-0.2.3/hackagent/models/generic_error_response.py +70 -0
  66. hackagent-0.2.3/hackagent/models/organization.py +102 -0
  67. hackagent-0.2.3/hackagent/models/organization_request.py +74 -0
  68. hackagent-0.2.3/hackagent/models/paginated_api_token_log_list.py +123 -0
  69. hackagent-0.2.3/hackagent/models/paginated_organization_list.py +123 -0
  70. hackagent-0.2.3/hackagent/models/paginated_user_profile_list.py +123 -0
  71. hackagent-0.2.3/hackagent/models/patched_organization_request.py +76 -0
  72. hackagent-0.2.3/hackagent/models/patched_user_profile_request.py +110 -0
  73. hackagent-0.2.3/hackagent/models/user_profile.py +135 -0
  74. hackagent-0.2.3/hackagent/models/user_profile_request.py +110 -0
  75. hackagent-0.2.3/hackagent/router/adapters/__init__.py +21 -0
  76. {hackagent-0.2.1/hackagent/router → hackagent-0.2.3/hackagent/router/adapters}/base.py +15 -0
  77. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/router/adapters/google_adk.py +1 -1
  78. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/router/adapters/litellm_adapter.py +73 -5
  79. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/router/router.py +221 -97
  80. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/types.py +14 -0
  81. hackagent-0.2.3/hackagent/utils.py +114 -0
  82. hackagent-0.2.1/hackagent/utils.py → hackagent-0.2.3/hackagent/vulnerabilities/prompts.py +15 -4
  83. {hackagent-0.2.1 → hackagent-0.2.3}/pyproject.toml +2 -2
  84. hackagent-0.2.1/hackagent/agent.py +0 -202
  85. hackagent-0.2.1/hackagent/api/generator/generator_create.py +0 -99
  86. hackagent-0.2.1/hackagent/api/judge/judge_create.py +0 -99
  87. hackagent-0.2.1/hackagent/branding.py +0 -42
  88. hackagent-0.2.1/hackagent/client.py +0 -333
  89. hackagent-0.2.1/hackagent/router/adapters/__init__.py +0 -5
  90. {hackagent-0.2.1 → hackagent-0.2.3}/LICENSE +0 -0
  91. {hackagent-0.2.1 → hackagent-0.2.3}/README.md +0 -0
  92. {hackagent-0.2.1 → hackagent-0.2.3}/assets/banner.png +0 -0
  93. {hackagent-0.2.1 → hackagent-0.2.3}/assets/favicon.ico +0 -0
  94. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/__init__.py +0 -0
  95. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/api/__init__.py +0 -0
  96. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/api/agent/__init__.py +0 -0
  97. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/api/agent/agent_create.py +0 -0
  98. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/api/agent/agent_list.py +0 -0
  99. {hackagent-0.2.1/hackagent/api/attack → hackagent-0.2.3/hackagent/api/apilogs}/__init__.py +0 -0
  100. {hackagent-0.2.1/hackagent/api/generator → hackagent-0.2.3/hackagent/api/attack}/__init__.py +0 -0
  101. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/api/attack/attack_create.py +0 -0
  102. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/api/attack/attack_list.py +0 -0
  103. {hackagent-0.2.1/hackagent/api/judge → hackagent-0.2.3/hackagent/api/checkout}/__init__.py +0 -0
  104. {hackagent-0.2.1/hackagent/api/key → hackagent-0.2.3/hackagent/api/generate}/__init__.py +0 -0
  105. {hackagent-0.2.1/hackagent/api/prompt → hackagent-0.2.3/hackagent/api/judge}/__init__.py +0 -0
  106. {hackagent-0.2.1/hackagent/api/result → hackagent-0.2.3/hackagent/api/key}/__init__.py +0 -0
  107. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/api/key/key_create.py +0 -0
  108. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/api/key/key_list.py +0 -0
  109. {hackagent-0.2.1/hackagent/api/run → hackagent-0.2.3/hackagent/api/organization}/__init__.py +0 -0
  110. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/api/prompt/prompt_create.py +0 -0
  111. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/api/prompt/prompt_list.py +0 -0
  112. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/api/result/result_create.py +0 -0
  113. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/api/result/result_list.py +0 -0
  114. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/api/run/run_create.py +0 -0
  115. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/api/run/run_run_tests_create.py +0 -0
  116. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/attacks/AdvPrefix/README.md +0 -0
  117. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/attacks/AdvPrefix/__init__.py +0 -0
  118. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/attacks/AdvPrefix/aggregation.py +0 -0
  119. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/attacks/AdvPrefix/completer.py +0 -0
  120. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/attacks/AdvPrefix/completions.py +0 -0
  121. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/attacks/AdvPrefix/compute_ce.py +0 -0
  122. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/attacks/AdvPrefix/evaluation.py +0 -0
  123. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/attacks/AdvPrefix/preprocessing.py +0 -0
  124. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/attacks/AdvPrefix/scorer.py +0 -0
  125. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/attacks/AdvPrefix/scorer_parser.py +0 -0
  126. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/attacks/AdvPrefix/selection.py +0 -0
  127. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/attacks/AdvPrefix/selector.py +0 -0
  128. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/attacks/AdvPrefix/utils.py +0 -0
  129. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/attacks/__init__.py +0 -0
  130. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/attacks/advprefix.py +0 -0
  131. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/attacks/base.py +0 -0
  132. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/attacks/strategies.py +0 -0
  133. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/models/agent.py +0 -0
  134. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/models/agent_request.py +0 -0
  135. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/models/agent_type_enum.py +0 -0
  136. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/models/attack.py +0 -0
  137. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/models/attack_request.py +0 -0
  138. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/models/evaluation_status_enum.py +0 -0
  139. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/models/organization_minimal.py +0 -0
  140. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/models/paginated_agent_list.py +0 -0
  141. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/models/paginated_attack_list.py +0 -0
  142. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/models/paginated_prompt_list.py +0 -0
  143. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/models/paginated_result_list.py +0 -0
  144. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/models/paginated_run_list.py +0 -0
  145. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/models/paginated_user_api_key_list.py +0 -0
  146. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/models/patched_agent_request.py +0 -0
  147. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/models/patched_attack_request.py +0 -0
  148. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/models/patched_prompt_request.py +0 -0
  149. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/models/patched_result_request.py +0 -0
  150. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/models/patched_run_request.py +0 -0
  151. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/models/prompt.py +0 -0
  152. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/models/prompt_request.py +0 -0
  153. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/models/result.py +0 -0
  154. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/models/result_list_evaluation_status.py +0 -0
  155. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/models/result_request.py +0 -0
  156. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/models/run.py +0 -0
  157. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/models/run_list_status.py +0 -0
  158. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/models/run_request.py +0 -0
  159. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/models/status_enum.py +0 -0
  160. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/models/step_type_enum.py +0 -0
  161. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/models/trace.py +0 -0
  162. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/models/trace_request.py +0 -0
  163. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/models/user_api_key.py +0 -0
  164. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/models/user_api_key_request.py +0 -0
  165. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/models/user_profile_minimal.py +0 -0
  166. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/py.typed +0 -0
  167. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/router/__init__.py +0 -0
  168. {hackagent-0.2.1 → hackagent-0.2.3}/hackagent/vulnerabilities/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: hackagent
3
- Version: 0.2.1
3
+ Version: 0.2.3
4
4
  Summary: HackAgent is an open-source security toolkit to detect vulnerabilities of your AI Agents.
5
5
  Author: Nicola Franco
6
6
  Author-email: nicola@vista-labs.ai
@@ -0,0 +1,212 @@
1
+ # Copyright 2025 - Vista Labs. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import logging
16
+ from typing import Any, Dict, Optional, Union
17
+
18
+ from hackagent.client import AuthenticatedClient
19
+ from hackagent.models import AgentTypeEnum
20
+ from hackagent.errors import HackAgentError
21
+ from hackagent.router import AgentRouter
22
+ from hackagent.vulnerabilities.prompts import DEFAULT_PROMPTS
23
+ from hackagent.attacks.strategies import AttackStrategy, AdvPrefix
24
+ from hackagent import utils
25
+
26
+ logger = logging.getLogger(__name__)
27
+
28
+
29
+ class HackAgent:
30
+ """
31
+ The primary client for orchestrating security assessments with HackAgent.
32
+
33
+ This class serves as the main entry point to the HackAgent library, providing
34
+ a high-level interface for:
35
+ - Configuring victim agents that will be assessed.
36
+ - Defining and selecting attack strategies.
37
+ - Executing automated security tests against the configured agents.
38
+ - Retrieving and handling test results.
39
+
40
+ It encapsulates complexities such as API authentication, agent registration
41
+ with the backend (via `AgentRouter`), and the dynamic dispatch of various
42
+ attack methodologies.
43
+
44
+ Attributes:
45
+ client: An `AuthenticatedClient` instance for API communication.
46
+ prompts: A dictionary of default prompts. This dictionary is a copy of
47
+ `DEFAULT_PROMPTS` and can be modified after instantiation if needed,
48
+ though the primary mechanism for custom prompts is usually via attack
49
+ configurations.
50
+ router: An `AgentRouter` instance managing the agent's representation
51
+ in the HackAgent backend.
52
+ attack_strategies: A dictionary mapping strategy names to their
53
+ `AttackStrategy` implementations.
54
+ """
55
+
56
+ def __init__(
57
+ self,
58
+ endpoint: str,
59
+ name: Optional[str] = None,
60
+ agent_type: Union[AgentTypeEnum, str] = AgentTypeEnum.UNKNOWN,
61
+ base_url: Optional[str] = None,
62
+ api_key: Optional[str] = None,
63
+ raise_on_unexpected_status: bool = False,
64
+ timeout: Optional[float] = None,
65
+ env_file_path: Optional[str] = None,
66
+ ):
67
+ """
68
+ Initializes the HackAgent client and prepares it for interaction.
69
+
70
+ This constructor sets up the authenticated API client, loads default
71
+ prompts, resolves the agent type, and initializes the agent router
72
+ to ensure the agent is known to the backend. It also prepares available
73
+ attack strategies.
74
+
75
+ Args:
76
+ endpoint: The target application's endpoint URL. This is the primary
77
+ interface that the configured agent will interact with or represent
78
+ during security tests.
79
+ name: An optional descriptive name for the agent being configured.
80
+ If not provided, a default name might be assigned or behavior might
81
+ depend on the specific backend agent management policies.
82
+ agent_type: Specifies the type of the agent. This can be provided
83
+ as an `AgentTypeEnum` member (e.g., `AgentTypeEnum.GOOGLE_ADK`) or
84
+ as a string identifier (e.g., "google-adk", "litellm").
85
+ String values are automatically converted to the corresponding
86
+ `AgentTypeEnum` member. Defaults to `AgentTypeEnum.UNKNOWN` if
87
+ not specified or if an invalid string is provided.
88
+ base_url: The base URL for the HackAgent API service.
89
+ api_key: The API key for authenticating with the HackAgent API.
90
+ If omitted, the client will attempt to retrieve it from the
91
+ `HACKAGENT_API_KEY` environment variable. The `env_file_path`
92
+ parameter can specify a .env file to load this variable from.
93
+ raise_on_unexpected_status: If set to `True`, the API client will
94
+ raise an exception for any HTTP status codes that are not typically
95
+ expected for a successful operation. Defaults to `False`.
96
+ timeout: The timeout duration in seconds for API requests made by the
97
+ authenticated client. Defaults to `None` (which might mean a
98
+ default timeout from the underlying HTTP library is used).
99
+ env_file_path: An optional path to a .env file. If provided, environment
100
+ variables (such as `HACKAGENT_API_KEY`) will be loaded from this
101
+ file if not already present in the environment.
102
+ """
103
+ utils.display_hackagent_splash()
104
+
105
+ resolved_auth_token = utils.resolve_api_token(
106
+ direct_api_key_param=api_key, env_file_path=env_file_path
107
+ )
108
+
109
+ self.client = AuthenticatedClient(
110
+ base_url=base_url,
111
+ token=resolved_auth_token,
112
+ prefix="Api-Key",
113
+ raise_on_unexpected_status=raise_on_unexpected_status,
114
+ timeout=timeout,
115
+ )
116
+
117
+ self.prompts = DEFAULT_PROMPTS.copy()
118
+
119
+ processed_agent_type = utils.resolve_agent_type(agent_type)
120
+
121
+ self.router = AgentRouter(
122
+ client=self.client,
123
+ name=name,
124
+ agent_type=processed_agent_type,
125
+ endpoint=endpoint,
126
+ )
127
+
128
+ self.attack_strategies: Dict[str, AttackStrategy] = {
129
+ "advprefix": AdvPrefix(hack_agent=self),
130
+ }
131
+
132
+ def hack(
133
+ self,
134
+ attack_config: Dict[str, Any],
135
+ run_config_override: Optional[Dict[str, Any]] = None,
136
+ fail_on_run_error: bool = True,
137
+ ) -> Any:
138
+ """
139
+ Executes a specified attack strategy against the configured victim agent.
140
+
141
+ This method serves as the primary action command for initiating an attack.
142
+ It identifies the appropriate attack strategy based on `attack_config`,
143
+ ensures the victim agent (managed by `self.router`) is ready, and then
144
+ delegates the execution to the chosen strategy.
145
+
146
+ Args:
147
+ attack_config: A dictionary containing parameters specific to the
148
+ chosen attack type. Must include an 'attack_type' key that maps
149
+ to a registered strategy (e.g., "advprefix"). Other keys provide
150
+ configuration for that strategy (e.g., 'category', 'prompt_text').
151
+ run_config_override: An optional dictionary that can override default
152
+ run configurations. The specifics depend on the attack strategy
153
+ and backend capabilities.
154
+ fail_on_run_error: If `True` (the default), an exception will be
155
+ raised if the attack run encounters an error and fails. If `False`,
156
+ errors might be suppressed or handled differently by the strategy.
157
+
158
+ Returns:
159
+ The result returned by the `execute` method of the chosen attack
160
+ strategy. The nature of this result is strategy-dependent.
161
+
162
+ Raises:
163
+ ValueError: If the 'attack_type' is missing from `attack_config` or
164
+ if the specified 'attack_type' is not a supported/registered
165
+ strategy.
166
+ HackAgentError: For issues during API interaction, problems with backend
167
+ agent operations, or other unexpected errors during the attack process.
168
+ """
169
+ try:
170
+ attack_type = attack_config.get("attack_type")
171
+ if not attack_type:
172
+ raise ValueError("'attack_type' must be provided in attack_config.")
173
+
174
+ strategy = self.attack_strategies.get(attack_type)
175
+ if not strategy:
176
+ supported_types = list(self.attack_strategies.keys())
177
+ raise ValueError(
178
+ f"Unsupported attack_type: {attack_type}. "
179
+ f"Supported types: {supported_types}."
180
+ )
181
+
182
+ backend_agent = self.router.backend_agent
183
+
184
+ logger.info(
185
+ f"Preparing to attack agent '{backend_agent.name}' "
186
+ f"(ID: {backend_agent.id}, Type: {backend_agent.agent_type.value}) "
187
+ f"configured in this HackAgent instance, using strategy '{attack_type}'."
188
+ )
189
+
190
+ return strategy.execute(
191
+ attack_config=attack_config,
192
+ run_config_override=run_config_override,
193
+ fail_on_run_error=fail_on_run_error,
194
+ )
195
+
196
+ except HackAgentError:
197
+ raise
198
+ except ValueError as ve:
199
+ logger.error(f"Configuration error in HackAgent.hack: {ve}", exc_info=True)
200
+ raise HackAgentError(f"Configuration error: {ve}") from ve
201
+ except RuntimeError as re:
202
+ logger.error(f"Runtime error during HackAgent.hack: {re}", exc_info=True)
203
+ if "Failed to create backend agent" in str(
204
+ re
205
+ ) or "Failed to update metadata" in str(re):
206
+ raise HackAgentError(f"Backend agent operation failed: {re}") from re
207
+ raise HackAgentError(f"An unexpected runtime error occurred: {re}") from re
208
+ except Exception as e:
209
+ logger.error(f"Unexpected error in HackAgent.hack: {e}", exc_info=True)
210
+ raise HackAgentError(
211
+ f"An unexpected error occurred during attack: {e}"
212
+ ) from e
@@ -14,9 +14,7 @@ def _get_kwargs(
14
14
  ) -> dict[str, Any]:
15
15
  _kwargs: dict[str, Any] = {
16
16
  "method": "delete",
17
- "url": "/api/agent/{id}".format(
18
- id=id,
19
- ),
17
+ "url": f"/api/agent/{id}",
20
18
  }
21
19
 
22
20
  return _kwargs
@@ -20,9 +20,7 @@ def _get_kwargs(
20
20
 
21
21
  _kwargs: dict[str, Any] = {
22
22
  "method": "patch",
23
- "url": "/api/agent/{id}".format(
24
- id=id,
25
- ),
23
+ "url": f"/api/agent/{id}",
26
24
  }
27
25
 
28
26
  _body = body.to_dict()
@@ -15,9 +15,7 @@ def _get_kwargs(
15
15
  ) -> dict[str, Any]:
16
16
  _kwargs: dict[str, Any] = {
17
17
  "method": "get",
18
- "url": "/api/agent/{id}".format(
19
- id=id,
20
- ),
18
+ "url": f"/api/agent/{id}",
21
19
  }
22
20
 
23
21
  return _kwargs
@@ -20,9 +20,7 @@ def _get_kwargs(
20
20
 
21
21
  _kwargs: dict[str, Any] = {
22
22
  "method": "put",
23
- "url": "/api/agent/{id}".format(
24
- id=id,
25
- ),
23
+ "url": f"/api/agent/{id}",
26
24
  }
27
25
 
28
26
  _body = body.to_dict()
@@ -0,0 +1,158 @@
1
+ from http import HTTPStatus
2
+ from typing import Any, Optional, Union
3
+
4
+ import httpx
5
+
6
+ from ... import errors
7
+ from ...client import AuthenticatedClient, Client
8
+ from ...models.paginated_api_token_log_list import PaginatedAPITokenLogList
9
+ from ...types import UNSET, Response, Unset
10
+
11
+
12
+ def _get_kwargs(
13
+ *,
14
+ page: Union[Unset, int] = UNSET,
15
+ ) -> dict[str, Any]:
16
+ params: dict[str, Any] = {}
17
+
18
+ params["page"] = page
19
+
20
+ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
21
+
22
+ _kwargs: dict[str, Any] = {
23
+ "method": "get",
24
+ "url": "/api/apilogs",
25
+ "params": params,
26
+ }
27
+
28
+ return _kwargs
29
+
30
+
31
+ def _parse_response(
32
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
33
+ ) -> Optional[PaginatedAPITokenLogList]:
34
+ if response.status_code == 200:
35
+ response_200 = PaginatedAPITokenLogList.from_dict(response.json())
36
+
37
+ return response_200
38
+ if client.raise_on_unexpected_status:
39
+ raise errors.UnexpectedStatus(response.status_code, response.content)
40
+ else:
41
+ return None
42
+
43
+
44
+ def _build_response(
45
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
46
+ ) -> Response[PaginatedAPITokenLogList]:
47
+ return Response(
48
+ status_code=HTTPStatus(response.status_code),
49
+ content=response.content,
50
+ headers=response.headers,
51
+ parsed=_parse_response(client=client, response=response),
52
+ )
53
+
54
+
55
+ def sync_detailed(
56
+ *,
57
+ client: AuthenticatedClient,
58
+ page: Union[Unset, int] = UNSET,
59
+ ) -> Response[PaginatedAPITokenLogList]:
60
+ """Provides read-only access to APITokenLog entries for the user's organization.
61
+
62
+ Args:
63
+ page (Union[Unset, int]):
64
+
65
+ Raises:
66
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
67
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
68
+
69
+ Returns:
70
+ Response[PaginatedAPITokenLogList]
71
+ """
72
+
73
+ kwargs = _get_kwargs(
74
+ page=page,
75
+ )
76
+
77
+ response = client.get_httpx_client().request(
78
+ **kwargs,
79
+ )
80
+
81
+ return _build_response(client=client, response=response)
82
+
83
+
84
+ def sync(
85
+ *,
86
+ client: AuthenticatedClient,
87
+ page: Union[Unset, int] = UNSET,
88
+ ) -> Optional[PaginatedAPITokenLogList]:
89
+ """Provides read-only access to APITokenLog entries for the user's organization.
90
+
91
+ Args:
92
+ page (Union[Unset, int]):
93
+
94
+ Raises:
95
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
96
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
97
+
98
+ Returns:
99
+ PaginatedAPITokenLogList
100
+ """
101
+
102
+ return sync_detailed(
103
+ client=client,
104
+ page=page,
105
+ ).parsed
106
+
107
+
108
+ async def asyncio_detailed(
109
+ *,
110
+ client: AuthenticatedClient,
111
+ page: Union[Unset, int] = UNSET,
112
+ ) -> Response[PaginatedAPITokenLogList]:
113
+ """Provides read-only access to APITokenLog entries for the user's organization.
114
+
115
+ Args:
116
+ page (Union[Unset, int]):
117
+
118
+ Raises:
119
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
120
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
121
+
122
+ Returns:
123
+ Response[PaginatedAPITokenLogList]
124
+ """
125
+
126
+ kwargs = _get_kwargs(
127
+ page=page,
128
+ )
129
+
130
+ response = await client.get_async_httpx_client().request(**kwargs)
131
+
132
+ return _build_response(client=client, response=response)
133
+
134
+
135
+ async def asyncio(
136
+ *,
137
+ client: AuthenticatedClient,
138
+ page: Union[Unset, int] = UNSET,
139
+ ) -> Optional[PaginatedAPITokenLogList]:
140
+ """Provides read-only access to APITokenLog entries for the user's organization.
141
+
142
+ Args:
143
+ page (Union[Unset, int]):
144
+
145
+ Raises:
146
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
147
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
148
+
149
+ Returns:
150
+ PaginatedAPITokenLogList
151
+ """
152
+
153
+ return (
154
+ await asyncio_detailed(
155
+ client=client,
156
+ page=page,
157
+ )
158
+ ).parsed
@@ -0,0 +1,150 @@
1
+ from http import HTTPStatus
2
+ from typing import Any, Optional, Union
3
+
4
+ import httpx
5
+
6
+ from ... import errors
7
+ from ...client import AuthenticatedClient, Client
8
+ from ...models.api_token_log import APITokenLog
9
+ from ...types import Response
10
+
11
+
12
+ def _get_kwargs(
13
+ id: int,
14
+ ) -> dict[str, Any]:
15
+ _kwargs: dict[str, Any] = {
16
+ "method": "get",
17
+ "url": f"/api/apilogs/{id}",
18
+ }
19
+
20
+ return _kwargs
21
+
22
+
23
+ def _parse_response(
24
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
25
+ ) -> Optional[APITokenLog]:
26
+ if response.status_code == 200:
27
+ response_200 = APITokenLog.from_dict(response.json())
28
+
29
+ return response_200
30
+ if client.raise_on_unexpected_status:
31
+ raise errors.UnexpectedStatus(response.status_code, response.content)
32
+ else:
33
+ return None
34
+
35
+
36
+ def _build_response(
37
+ *, client: Union[AuthenticatedClient, Client], response: httpx.Response
38
+ ) -> Response[APITokenLog]:
39
+ return Response(
40
+ status_code=HTTPStatus(response.status_code),
41
+ content=response.content,
42
+ headers=response.headers,
43
+ parsed=_parse_response(client=client, response=response),
44
+ )
45
+
46
+
47
+ def sync_detailed(
48
+ id: int,
49
+ *,
50
+ client: AuthenticatedClient,
51
+ ) -> Response[APITokenLog]:
52
+ """Provides read-only access to APITokenLog entries for the user's organization.
53
+
54
+ Args:
55
+ id (int):
56
+
57
+ Raises:
58
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
59
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
60
+
61
+ Returns:
62
+ Response[APITokenLog]
63
+ """
64
+
65
+ kwargs = _get_kwargs(
66
+ id=id,
67
+ )
68
+
69
+ response = client.get_httpx_client().request(
70
+ **kwargs,
71
+ )
72
+
73
+ return _build_response(client=client, response=response)
74
+
75
+
76
+ def sync(
77
+ id: int,
78
+ *,
79
+ client: AuthenticatedClient,
80
+ ) -> Optional[APITokenLog]:
81
+ """Provides read-only access to APITokenLog entries for the user's organization.
82
+
83
+ Args:
84
+ id (int):
85
+
86
+ Raises:
87
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
88
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
89
+
90
+ Returns:
91
+ APITokenLog
92
+ """
93
+
94
+ return sync_detailed(
95
+ id=id,
96
+ client=client,
97
+ ).parsed
98
+
99
+
100
+ async def asyncio_detailed(
101
+ id: int,
102
+ *,
103
+ client: AuthenticatedClient,
104
+ ) -> Response[APITokenLog]:
105
+ """Provides read-only access to APITokenLog entries for the user's organization.
106
+
107
+ Args:
108
+ id (int):
109
+
110
+ Raises:
111
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
112
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
113
+
114
+ Returns:
115
+ Response[APITokenLog]
116
+ """
117
+
118
+ kwargs = _get_kwargs(
119
+ id=id,
120
+ )
121
+
122
+ response = await client.get_async_httpx_client().request(**kwargs)
123
+
124
+ return _build_response(client=client, response=response)
125
+
126
+
127
+ async def asyncio(
128
+ id: int,
129
+ *,
130
+ client: AuthenticatedClient,
131
+ ) -> Optional[APITokenLog]:
132
+ """Provides read-only access to APITokenLog entries for the user's organization.
133
+
134
+ Args:
135
+ id (int):
136
+
137
+ Raises:
138
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
139
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
140
+
141
+ Returns:
142
+ APITokenLog
143
+ """
144
+
145
+ return (
146
+ await asyncio_detailed(
147
+ id=id,
148
+ client=client,
149
+ )
150
+ ).parsed
@@ -14,9 +14,7 @@ def _get_kwargs(
14
14
  ) -> dict[str, Any]:
15
15
  _kwargs: dict[str, Any] = {
16
16
  "method": "delete",
17
- "url": "/api/attack/{id}".format(
18
- id=id,
19
- ),
17
+ "url": f"/api/attack/{id}",
20
18
  }
21
19
 
22
20
  return _kwargs
@@ -20,9 +20,7 @@ def _get_kwargs(
20
20
 
21
21
  _kwargs: dict[str, Any] = {
22
22
  "method": "patch",
23
- "url": "/api/attack/{id}".format(
24
- id=id,
25
- ),
23
+ "url": f"/api/attack/{id}",
26
24
  }
27
25
 
28
26
  _body = body.to_dict()
@@ -15,9 +15,7 @@ def _get_kwargs(
15
15
  ) -> dict[str, Any]:
16
16
  _kwargs: dict[str, Any] = {
17
17
  "method": "get",
18
- "url": "/api/attack/{id}".format(
19
- id=id,
20
- ),
18
+ "url": f"/api/attack/{id}",
21
19
  }
22
20
 
23
21
  return _kwargs
@@ -20,9 +20,7 @@ def _get_kwargs(
20
20
 
21
21
  _kwargs: dict[str, Any] = {
22
22
  "method": "put",
23
- "url": "/api/attack/{id}".format(
24
- id=id,
25
- ),
23
+ "url": f"/api/attack/{id}",
26
24
  }
27
25
 
28
26
  _body = body.to_dict()