hackagent 0.3.1__py3-none-any.whl

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 (183) hide show
  1. hackagent/__init__.py +12 -0
  2. hackagent/agent.py +214 -0
  3. hackagent/api/__init__.py +1 -0
  4. hackagent/api/agent/__init__.py +1 -0
  5. hackagent/api/agent/agent_create.py +347 -0
  6. hackagent/api/agent/agent_destroy.py +140 -0
  7. hackagent/api/agent/agent_list.py +242 -0
  8. hackagent/api/agent/agent_partial_update.py +361 -0
  9. hackagent/api/agent/agent_retrieve.py +235 -0
  10. hackagent/api/agent/agent_update.py +361 -0
  11. hackagent/api/apilogs/__init__.py +1 -0
  12. hackagent/api/apilogs/apilogs_list.py +170 -0
  13. hackagent/api/apilogs/apilogs_retrieve.py +162 -0
  14. hackagent/api/attack/__init__.py +1 -0
  15. hackagent/api/attack/attack_create.py +275 -0
  16. hackagent/api/attack/attack_destroy.py +146 -0
  17. hackagent/api/attack/attack_list.py +254 -0
  18. hackagent/api/attack/attack_partial_update.py +289 -0
  19. hackagent/api/attack/attack_retrieve.py +247 -0
  20. hackagent/api/attack/attack_update.py +289 -0
  21. hackagent/api/checkout/__init__.py +1 -0
  22. hackagent/api/checkout/checkout_create.py +225 -0
  23. hackagent/api/generate/__init__.py +1 -0
  24. hackagent/api/generate/generate_create.py +253 -0
  25. hackagent/api/judge/__init__.py +1 -0
  26. hackagent/api/judge/judge_create.py +253 -0
  27. hackagent/api/key/__init__.py +1 -0
  28. hackagent/api/key/key_create.py +179 -0
  29. hackagent/api/key/key_destroy.py +103 -0
  30. hackagent/api/key/key_list.py +170 -0
  31. hackagent/api/key/key_retrieve.py +162 -0
  32. hackagent/api/organization/__init__.py +1 -0
  33. hackagent/api/organization/organization_create.py +208 -0
  34. hackagent/api/organization/organization_destroy.py +104 -0
  35. hackagent/api/organization/organization_list.py +170 -0
  36. hackagent/api/organization/organization_me_retrieve.py +126 -0
  37. hackagent/api/organization/organization_partial_update.py +222 -0
  38. hackagent/api/organization/organization_retrieve.py +163 -0
  39. hackagent/api/organization/organization_update.py +222 -0
  40. hackagent/api/prompt/__init__.py +1 -0
  41. hackagent/api/prompt/prompt_create.py +171 -0
  42. hackagent/api/prompt/prompt_destroy.py +104 -0
  43. hackagent/api/prompt/prompt_list.py +185 -0
  44. hackagent/api/prompt/prompt_partial_update.py +185 -0
  45. hackagent/api/prompt/prompt_retrieve.py +163 -0
  46. hackagent/api/prompt/prompt_update.py +185 -0
  47. hackagent/api/result/__init__.py +1 -0
  48. hackagent/api/result/result_create.py +175 -0
  49. hackagent/api/result/result_destroy.py +106 -0
  50. hackagent/api/result/result_list.py +249 -0
  51. hackagent/api/result/result_partial_update.py +193 -0
  52. hackagent/api/result/result_retrieve.py +167 -0
  53. hackagent/api/result/result_trace_create.py +177 -0
  54. hackagent/api/result/result_update.py +189 -0
  55. hackagent/api/run/__init__.py +1 -0
  56. hackagent/api/run/run_create.py +187 -0
  57. hackagent/api/run/run_destroy.py +112 -0
  58. hackagent/api/run/run_list.py +291 -0
  59. hackagent/api/run/run_partial_update.py +201 -0
  60. hackagent/api/run/run_result_create.py +177 -0
  61. hackagent/api/run/run_retrieve.py +179 -0
  62. hackagent/api/run/run_run_tests_create.py +187 -0
  63. hackagent/api/run/run_update.py +201 -0
  64. hackagent/api/user/__init__.py +1 -0
  65. hackagent/api/user/user_create.py +212 -0
  66. hackagent/api/user/user_destroy.py +106 -0
  67. hackagent/api/user/user_list.py +174 -0
  68. hackagent/api/user/user_me_retrieve.py +126 -0
  69. hackagent/api/user/user_me_update.py +196 -0
  70. hackagent/api/user/user_partial_update.py +226 -0
  71. hackagent/api/user/user_retrieve.py +167 -0
  72. hackagent/api/user/user_update.py +226 -0
  73. hackagent/attacks/AdvPrefix/__init__.py +41 -0
  74. hackagent/attacks/AdvPrefix/completions.py +416 -0
  75. hackagent/attacks/AdvPrefix/config.py +259 -0
  76. hackagent/attacks/AdvPrefix/evaluation.py +745 -0
  77. hackagent/attacks/AdvPrefix/evaluators.py +564 -0
  78. hackagent/attacks/AdvPrefix/generate.py +711 -0
  79. hackagent/attacks/AdvPrefix/utils.py +307 -0
  80. hackagent/attacks/__init__.py +35 -0
  81. hackagent/attacks/advprefix.py +507 -0
  82. hackagent/attacks/base.py +106 -0
  83. hackagent/attacks/strategies.py +906 -0
  84. hackagent/cli/__init__.py +19 -0
  85. hackagent/cli/commands/__init__.py +20 -0
  86. hackagent/cli/commands/agent.py +100 -0
  87. hackagent/cli/commands/attack.py +417 -0
  88. hackagent/cli/commands/config.py +301 -0
  89. hackagent/cli/commands/results.py +327 -0
  90. hackagent/cli/config.py +249 -0
  91. hackagent/cli/main.py +515 -0
  92. hackagent/cli/tui/__init__.py +31 -0
  93. hackagent/cli/tui/actions_logger.py +200 -0
  94. hackagent/cli/tui/app.py +288 -0
  95. hackagent/cli/tui/base.py +137 -0
  96. hackagent/cli/tui/logger.py +318 -0
  97. hackagent/cli/tui/views/__init__.py +33 -0
  98. hackagent/cli/tui/views/agents.py +488 -0
  99. hackagent/cli/tui/views/attacks.py +624 -0
  100. hackagent/cli/tui/views/config.py +244 -0
  101. hackagent/cli/tui/views/dashboard.py +307 -0
  102. hackagent/cli/tui/views/results.py +1210 -0
  103. hackagent/cli/tui/widgets/__init__.py +24 -0
  104. hackagent/cli/tui/widgets/actions.py +346 -0
  105. hackagent/cli/tui/widgets/logs.py +435 -0
  106. hackagent/cli/utils.py +276 -0
  107. hackagent/client.py +286 -0
  108. hackagent/errors.py +37 -0
  109. hackagent/logger.py +83 -0
  110. hackagent/models/__init__.py +109 -0
  111. hackagent/models/agent.py +223 -0
  112. hackagent/models/agent_request.py +129 -0
  113. hackagent/models/api_token_log.py +184 -0
  114. hackagent/models/attack.py +154 -0
  115. hackagent/models/attack_request.py +82 -0
  116. hackagent/models/checkout_session_request_request.py +76 -0
  117. hackagent/models/checkout_session_response.py +59 -0
  118. hackagent/models/choice.py +81 -0
  119. hackagent/models/choice_message.py +67 -0
  120. hackagent/models/evaluation_status_enum.py +14 -0
  121. hackagent/models/generate_error_response.py +59 -0
  122. hackagent/models/generate_request_request.py +212 -0
  123. hackagent/models/generate_success_response.py +115 -0
  124. hackagent/models/generic_error_response.py +70 -0
  125. hackagent/models/message_request.py +67 -0
  126. hackagent/models/organization.py +102 -0
  127. hackagent/models/organization_minimal.py +68 -0
  128. hackagent/models/organization_request.py +71 -0
  129. hackagent/models/paginated_agent_list.py +123 -0
  130. hackagent/models/paginated_api_token_log_list.py +123 -0
  131. hackagent/models/paginated_attack_list.py +123 -0
  132. hackagent/models/paginated_organization_list.py +123 -0
  133. hackagent/models/paginated_prompt_list.py +123 -0
  134. hackagent/models/paginated_result_list.py +123 -0
  135. hackagent/models/paginated_run_list.py +123 -0
  136. hackagent/models/paginated_user_api_key_list.py +123 -0
  137. hackagent/models/paginated_user_profile_list.py +123 -0
  138. hackagent/models/patched_agent_request.py +128 -0
  139. hackagent/models/patched_attack_request.py +92 -0
  140. hackagent/models/patched_organization_request.py +71 -0
  141. hackagent/models/patched_prompt_request.py +125 -0
  142. hackagent/models/patched_result_request.py +237 -0
  143. hackagent/models/patched_run_request.py +138 -0
  144. hackagent/models/patched_user_profile_request.py +99 -0
  145. hackagent/models/prompt.py +220 -0
  146. hackagent/models/prompt_request.py +126 -0
  147. hackagent/models/result.py +294 -0
  148. hackagent/models/result_list_evaluation_status.py +14 -0
  149. hackagent/models/result_request.py +232 -0
  150. hackagent/models/run.py +233 -0
  151. hackagent/models/run_list_status.py +12 -0
  152. hackagent/models/run_request.py +133 -0
  153. hackagent/models/status_enum.py +12 -0
  154. hackagent/models/step_type_enum.py +14 -0
  155. hackagent/models/trace.py +121 -0
  156. hackagent/models/trace_request.py +94 -0
  157. hackagent/models/usage.py +75 -0
  158. hackagent/models/user_api_key.py +201 -0
  159. hackagent/models/user_api_key_request.py +73 -0
  160. hackagent/models/user_profile.py +135 -0
  161. hackagent/models/user_profile_minimal.py +76 -0
  162. hackagent/models/user_profile_request.py +99 -0
  163. hackagent/router/__init__.py +25 -0
  164. hackagent/router/adapters/__init__.py +20 -0
  165. hackagent/router/adapters/base.py +63 -0
  166. hackagent/router/adapters/google_adk.py +671 -0
  167. hackagent/router/adapters/litellm_adapter.py +524 -0
  168. hackagent/router/adapters/openai_adapter.py +426 -0
  169. hackagent/router/router.py +969 -0
  170. hackagent/router/types.py +54 -0
  171. hackagent/tracking/__init__.py +42 -0
  172. hackagent/tracking/context.py +163 -0
  173. hackagent/tracking/decorators.py +299 -0
  174. hackagent/tracking/tracker.py +441 -0
  175. hackagent/types.py +54 -0
  176. hackagent/utils.py +194 -0
  177. hackagent/vulnerabilities/__init__.py +13 -0
  178. hackagent/vulnerabilities/prompts.py +81 -0
  179. hackagent-0.3.1.dist-info/METADATA +122 -0
  180. hackagent-0.3.1.dist-info/RECORD +183 -0
  181. hackagent-0.3.1.dist-info/WHEEL +4 -0
  182. hackagent-0.3.1.dist-info/entry_points.txt +2 -0
  183. hackagent-0.3.1.dist-info/licenses/LICENSE +202 -0
@@ -0,0 +1,307 @@
1
+ # Copyright 2025 - AI4I. 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
+ """
16
+ Utility functions for AdvPrefix attacks.
17
+
18
+ This module provides common utility functions and helper methods used across
19
+ the AdvPrefix attack pipeline. All execution data is tracked via the API.
20
+
21
+ The module provides:
22
+ - Progress bar context managers for visual feedback
23
+ - LLM completion utilities for model interactions
24
+ - Processor step execution with standardized error handling
25
+ - String processing and text manipulation functions
26
+ - Common mathematical and statistical operations
27
+
28
+ These utilities promote code reuse and maintain consistency across the
29
+ different stages of the AdvPrefix attack pipeline.
30
+ """
31
+
32
+ import functools
33
+ import logging
34
+ from contextlib import contextmanager
35
+ from typing import (
36
+ Any,
37
+ Callable,
38
+ List,
39
+ Optional,
40
+ TypeVar,
41
+ )
42
+
43
+ # Import Rich progress bar components
44
+ from rich.progress import (
45
+ BarColumn,
46
+ MofNCompleteColumn,
47
+ Progress,
48
+ SpinnerColumn,
49
+ TextColumn,
50
+ TimeRemainingColumn,
51
+ )
52
+
53
+ # Use hierarchical logger name for TUI handler inheritance
54
+ logger = logging.getLogger("hackagent.attacks.advprefix.utils")
55
+
56
+ # --- Constants ---
57
+
58
+ # Refusal keywords used for detecting model refusals across pipeline steps
59
+ REFUSAL_KEYWORDS = [
60
+ "i'm sorry",
61
+ "i cannot",
62
+ "i am not able",
63
+ "i'm not supposed to",
64
+ "i am unable",
65
+ "as an ai",
66
+ "my apologies",
67
+ "it's not appropriate",
68
+ "i am programmed",
69
+ "violates my guidelines",
70
+ ]
71
+
72
+
73
+ @contextmanager
74
+ def create_progress_bar(description: str, total: int):
75
+ """
76
+ Create a standardized progress bar for AdvPrefix pipeline steps.
77
+
78
+ This context manager provides a consistent progress bar configuration
79
+ across all pipeline stages, eliminating code duplication and ensuring
80
+ uniform progress reporting UX throughout the attack execution.
81
+
82
+ The progress bar includes:
83
+ - Spinner animation for visual feedback
84
+ - Task description with formatting support
85
+ - Visual progress bar
86
+ - Completion counter (M of N complete)
87
+ - Percentage complete
88
+ - Estimated time remaining
89
+
90
+ Args:
91
+ description: Human-readable description of the task being tracked.
92
+ Supports Rich markup formatting (e.g., "[cyan]Processing...[/cyan]").
93
+ total: Total number of items/iterations to process for completion tracking.
94
+
95
+ Yields:
96
+ Tuple of (progress_bar, task_id):
97
+ - progress_bar: Progress instance for manual control if needed
98
+ - task_id: Task identifier for progress updates via progress_bar.update(task_id)
99
+
100
+ Example:
101
+ >>> with create_progress_bar("[cyan]Processing prefixes...", len(data)) as (progress, task):
102
+ ... for item in data:
103
+ ... # Process item
104
+ ... progress.update(task, advance=1)
105
+
106
+ Note:
107
+ The progress bar automatically starts and stops when entering/exiting
108
+ the context manager. All pipeline steps should use this utility for
109
+ consistent progress reporting.
110
+ """
111
+ # Check if running in TUI mode (NO_COLOR env var is set by TUI)
112
+ import os
113
+
114
+ in_tui_mode = os.environ.get("NO_COLOR") == "1"
115
+
116
+ if in_tui_mode:
117
+ # In TUI mode: use a null progress bar that does nothing
118
+ class NullProgress:
119
+ def add_task(self, *args, **kwargs):
120
+ return 0
121
+
122
+ def update(self, *args, **kwargs):
123
+ pass
124
+
125
+ def __enter__(self):
126
+ return self
127
+
128
+ def __exit__(self, *args):
129
+ pass
130
+
131
+ progress_bar = NullProgress()
132
+ task = 0
133
+ yield progress_bar, task
134
+ else:
135
+ # Normal mode: use Rich progress bar
136
+ with Progress(
137
+ SpinnerColumn(),
138
+ TextColumn("[progress.description]{task.description}"),
139
+ BarColumn(),
140
+ MofNCompleteColumn(),
141
+ TextColumn("[progress.percentage]{task.percentage:>3.1f}%"),
142
+ TimeRemainingColumn(),
143
+ ) as progress_bar:
144
+ task = progress_bar.add_task(description, total=total)
145
+ yield progress_bar, task
146
+
147
+
148
+ # Checkpoint functionality removed - all tracking via API
149
+
150
+
151
+ # ============================================================================
152
+ # PIPELINE DECORATORS
153
+ # ============================================================================
154
+
155
+ # Type variable for function signatures
156
+ F = TypeVar("F", bound=Callable[..., Any])
157
+
158
+
159
+ def handle_empty_input(step_name: str, empty_result: Any = None):
160
+ """
161
+ Decorator to handle empty input data (list/dict).
162
+
163
+ Args:
164
+ step_name: Step name for logging
165
+ empty_result: What to return if input is empty (default: empty list)
166
+
167
+ Example:
168
+ >>> @handle_empty_input("Generate Prefixes", empty_result=[])
169
+ ... def execute(goals, config, logger, client):
170
+ ... # goals will never be empty here
171
+ ... return results
172
+ """
173
+
174
+ def decorator(func: F) -> F:
175
+ @functools.wraps(func)
176
+ def wrapper(*args, **kwargs):
177
+ logger_instance = kwargs.get("logger") or logging.getLogger(func.__module__)
178
+
179
+ # Check for empty input in common parameter names
180
+ for key in ["input_df", "data", "goals"]:
181
+ if key in kwargs:
182
+ value = kwargs[key]
183
+ if isinstance(value, list) and len(value) == 0:
184
+ logger_instance.warning(
185
+ f"{step_name} received empty data. Skipping."
186
+ )
187
+ return empty_result if empty_result is not None else []
188
+ elif isinstance(value, dict) and len(value) == 0:
189
+ logger_instance.warning(
190
+ f"{step_name} received empty data. Skipping."
191
+ )
192
+ return empty_result if empty_result is not None else []
193
+
194
+ return func(*args, **kwargs)
195
+
196
+ return wrapper # type: ignore
197
+
198
+ return decorator
199
+
200
+
201
+ def require_agent_router(step_name: str, agent_type: Optional[str] = None):
202
+ """
203
+ Decorator to validate agent_router parameter exists and is valid.
204
+
205
+ Args:
206
+ step_name: Step name for error messages
207
+ agent_type: Optional required agent type (e.g., "GOOGLE_ADK")
208
+
209
+ Example:
210
+ >>> @require_agent_router("Compute CE", agent_type="GOOGLE_ADK")
211
+ ... def execute(client, agent_router, input_df, config, logger):
212
+ ... # agent_router is guaranteed to be valid here
213
+ ... pass
214
+ """
215
+
216
+ def decorator(func: F) -> F:
217
+ @functools.wraps(func)
218
+ def wrapper(*args, **kwargs):
219
+ logger_instance = kwargs.get("logger") or logging.getLogger(func.__module__)
220
+ agent_router = kwargs.get("agent_router")
221
+
222
+ if (
223
+ not agent_router
224
+ or not hasattr(agent_router, "backend_agent")
225
+ or not agent_router.backend_agent
226
+ ):
227
+ msg = f"{step_name}: Valid agent_router with backend_agent required"
228
+ logger_instance.error(msg)
229
+ raise ValueError(msg)
230
+
231
+ # agent_type is already a string, not an enum
232
+ actual_agent_type = agent_router.backend_agent.agent_type
233
+ if agent_type and actual_agent_type != agent_type:
234
+ msg = (
235
+ f"{step_name}: Requires {agent_type} agent, got {actual_agent_type}"
236
+ )
237
+ logger_instance.error(msg)
238
+ raise ValueError(msg)
239
+
240
+ return func(*args, **kwargs)
241
+
242
+ return wrapper # type: ignore
243
+
244
+ return decorator
245
+
246
+
247
+ def log_errors(step_name: str):
248
+ """
249
+ Decorator to add consistent error logging.
250
+
251
+ Args:
252
+ step_name: Step name for error messages
253
+
254
+ Example:
255
+ >>> @log_errors("Generate Prefixes")
256
+ ... def execute(goals, config, logger, client):
257
+ ... # Any exception will be logged with step context
258
+ ... return results
259
+ """
260
+
261
+ def decorator(func: F) -> F:
262
+ @functools.wraps(func)
263
+ def wrapper(*args, **kwargs):
264
+ logger_instance = kwargs.get("logger") or logging.getLogger(func.__module__)
265
+
266
+ try:
267
+ return func(*args, **kwargs)
268
+ except Exception as e:
269
+ logger_instance.error(f"{step_name} failed: {e}", exc_info=True)
270
+ raise
271
+
272
+ return wrapper # type: ignore
273
+
274
+ return decorator
275
+
276
+
277
+ def validate_config(required_keys: List[str]):
278
+ """
279
+ Decorator to validate configuration has required keys.
280
+
281
+ Args:
282
+ required_keys: List of required configuration keys
283
+
284
+ Example:
285
+ >>> @validate_config(["model_id", "temperature", "max_tokens"])
286
+ ... def execute(config, logger):
287
+ ... # config is guaranteed to have required keys
288
+ ... pass
289
+ """
290
+
291
+ def decorator(func: F) -> F:
292
+ @functools.wraps(func)
293
+ def wrapper(*args, **kwargs):
294
+ logger_instance = kwargs.get("logger") or logging.getLogger(func.__module__)
295
+ config = kwargs.get("config", {})
296
+
297
+ missing = [k for k in required_keys if k not in config]
298
+ if missing:
299
+ msg = f"Missing required config keys: {', '.join(missing)}"
300
+ logger_instance.error(msg)
301
+ raise ValueError(msg)
302
+
303
+ return func(*args, **kwargs)
304
+
305
+ return wrapper # type: ignore
306
+
307
+ return decorator
@@ -0,0 +1,35 @@
1
+ # Copyright 2025 - AI4I. 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
+ """
16
+ Attack module for HackAgent security assessment framework.
17
+
18
+ This package contains various attack implementations designed to test the security
19
+ and robustness of AI agents and language models. The attacks are built on a common
20
+ base class and follow established patterns for extensibility and maintainability.
21
+
22
+ Available attacks:
23
+ - AdvPrefix: Adversarial prefix generation attacks using uncensored and target models
24
+ - Base attack classes and utilities for implementing new attack types
25
+ - Strategy pattern implementations for flexible attack execution
26
+
27
+ The module integrates with the HackAgent backend for result tracking and reporting.
28
+ """
29
+
30
+ from .strategies import AdvPrefix, AttackStrategy
31
+
32
+ __all__ = [
33
+ "AttackStrategy",
34
+ "AdvPrefix",
35
+ ]