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,232 @@
1
+ from collections.abc import Mapping
2
+ from typing import Any, TypeVar, Union, cast
3
+ from uuid import UUID
4
+
5
+ from attrs import define as _attrs_define
6
+ from attrs import field as _attrs_field
7
+
8
+ from ..models.evaluation_status_enum import EvaluationStatusEnum
9
+ from ..types import UNSET, Unset
10
+
11
+ T = TypeVar("T", bound="ResultRequest")
12
+
13
+
14
+ @_attrs_define
15
+ class ResultRequest:
16
+ """Serializer for the Result model, often nested in RunSerializer.
17
+
18
+ Attributes:
19
+ run (UUID):
20
+ prompt (Union[None, UUID, Unset]):
21
+ request_payload (Union[Unset, Any]): Payload sent to agent or relevant data for client-submitted results.
22
+ response_status_code (Union[None, Unset, int]):
23
+ response_headers (Union[Unset, Any]):
24
+ response_body (Union[None, Unset, str]):
25
+ latency_ms (Union[None, Unset, int]):
26
+ detected_tool_calls (Union[Unset, Any]):
27
+ evaluation_status (Union[Unset, EvaluationStatusEnum]): * `NOT_EVALUATED` - Not Evaluated
28
+ * `SUCCESSFUL_JAILBREAK` - Successful Jailbreak
29
+ * `FAILED_JAILBREAK` - Failed Jailbreak (Mitigated/Refused)
30
+ * `ERROR_AGENT_RESPONSE` - Error in Agent Response
31
+ * `ERROR_TEST_FRAMEWORK` - Error in Test Framework
32
+ * `PASSED_CRITERIA` - Passed Criteria (Not Jailbreak)
33
+ * `FAILED_CRITERIA` - Failed Criteria (Not Jailbreak)
34
+ evaluation_notes (Union[Unset, str]):
35
+ evaluation_metrics (Union[Unset, Any]):
36
+ agent_specific_data (Union[Unset, Any]):
37
+ """
38
+
39
+ run: UUID
40
+ prompt: Union[None, UUID, Unset] = UNSET
41
+ request_payload: Union[Unset, Any] = UNSET
42
+ response_status_code: Union[None, Unset, int] = UNSET
43
+ response_headers: Union[Unset, Any] = UNSET
44
+ response_body: Union[None, Unset, str] = UNSET
45
+ latency_ms: Union[None, Unset, int] = UNSET
46
+ detected_tool_calls: Union[Unset, Any] = UNSET
47
+ evaluation_status: Union[Unset, EvaluationStatusEnum] = UNSET
48
+ evaluation_notes: Union[Unset, str] = UNSET
49
+ evaluation_metrics: Union[Unset, Any] = UNSET
50
+ agent_specific_data: Union[Unset, Any] = UNSET
51
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
52
+
53
+ def to_dict(self) -> dict[str, Any]:
54
+ run = str(self.run)
55
+
56
+ prompt: Union[None, Unset, str]
57
+ if isinstance(self.prompt, Unset):
58
+ prompt = UNSET
59
+ elif isinstance(self.prompt, UUID):
60
+ prompt = str(self.prompt)
61
+ else:
62
+ prompt = self.prompt
63
+
64
+ request_payload = self.request_payload
65
+
66
+ response_status_code: Union[None, Unset, int]
67
+ if isinstance(self.response_status_code, Unset):
68
+ response_status_code = UNSET
69
+ else:
70
+ response_status_code = self.response_status_code
71
+
72
+ response_headers = self.response_headers
73
+
74
+ response_body: Union[None, Unset, str]
75
+ if isinstance(self.response_body, Unset):
76
+ response_body = UNSET
77
+ else:
78
+ response_body = self.response_body
79
+
80
+ latency_ms: Union[None, Unset, int]
81
+ if isinstance(self.latency_ms, Unset):
82
+ latency_ms = UNSET
83
+ else:
84
+ latency_ms = self.latency_ms
85
+
86
+ detected_tool_calls = self.detected_tool_calls
87
+
88
+ evaluation_status: Union[Unset, str] = UNSET
89
+ if not isinstance(self.evaluation_status, Unset):
90
+ evaluation_status = self.evaluation_status.value
91
+
92
+ evaluation_notes = self.evaluation_notes
93
+
94
+ evaluation_metrics = self.evaluation_metrics
95
+
96
+ agent_specific_data = self.agent_specific_data
97
+
98
+ field_dict: dict[str, Any] = {}
99
+ field_dict.update(self.additional_properties)
100
+ field_dict.update(
101
+ {
102
+ "run": run,
103
+ }
104
+ )
105
+ if prompt is not UNSET:
106
+ field_dict["prompt"] = prompt
107
+ if request_payload is not UNSET:
108
+ field_dict["request_payload"] = request_payload
109
+ if response_status_code is not UNSET:
110
+ field_dict["response_status_code"] = response_status_code
111
+ if response_headers is not UNSET:
112
+ field_dict["response_headers"] = response_headers
113
+ if response_body is not UNSET:
114
+ field_dict["response_body"] = response_body
115
+ if latency_ms is not UNSET:
116
+ field_dict["latency_ms"] = latency_ms
117
+ if detected_tool_calls is not UNSET:
118
+ field_dict["detected_tool_calls"] = detected_tool_calls
119
+ if evaluation_status is not UNSET:
120
+ field_dict["evaluation_status"] = evaluation_status
121
+ if evaluation_notes is not UNSET:
122
+ field_dict["evaluation_notes"] = evaluation_notes
123
+ if evaluation_metrics is not UNSET:
124
+ field_dict["evaluation_metrics"] = evaluation_metrics
125
+ if agent_specific_data is not UNSET:
126
+ field_dict["agent_specific_data"] = agent_specific_data
127
+
128
+ return field_dict
129
+
130
+ @classmethod
131
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
132
+ d = dict(src_dict)
133
+ run = UUID(d.pop("run"))
134
+
135
+ def _parse_prompt(data: object) -> Union[None, UUID, Unset]:
136
+ if data is None:
137
+ return data
138
+ if isinstance(data, Unset):
139
+ return data
140
+ try:
141
+ if not isinstance(data, str):
142
+ raise TypeError()
143
+ prompt_type_0 = UUID(data)
144
+
145
+ return prompt_type_0
146
+ except: # noqa: E722
147
+ pass
148
+ return cast(Union[None, UUID, Unset], data)
149
+
150
+ prompt = _parse_prompt(d.pop("prompt", UNSET))
151
+
152
+ request_payload = d.pop("request_payload", UNSET)
153
+
154
+ def _parse_response_status_code(data: object) -> Union[None, Unset, int]:
155
+ if data is None:
156
+ return data
157
+ if isinstance(data, Unset):
158
+ return data
159
+ return cast(Union[None, Unset, int], data)
160
+
161
+ response_status_code = _parse_response_status_code(
162
+ d.pop("response_status_code", UNSET)
163
+ )
164
+
165
+ response_headers = d.pop("response_headers", UNSET)
166
+
167
+ def _parse_response_body(data: object) -> Union[None, Unset, str]:
168
+ if data is None:
169
+ return data
170
+ if isinstance(data, Unset):
171
+ return data
172
+ return cast(Union[None, Unset, str], data)
173
+
174
+ response_body = _parse_response_body(d.pop("response_body", UNSET))
175
+
176
+ def _parse_latency_ms(data: object) -> Union[None, Unset, int]:
177
+ if data is None:
178
+ return data
179
+ if isinstance(data, Unset):
180
+ return data
181
+ return cast(Union[None, Unset, int], data)
182
+
183
+ latency_ms = _parse_latency_ms(d.pop("latency_ms", UNSET))
184
+
185
+ detected_tool_calls = d.pop("detected_tool_calls", UNSET)
186
+
187
+ _evaluation_status = d.pop("evaluation_status", UNSET)
188
+ evaluation_status: Union[Unset, EvaluationStatusEnum]
189
+ if isinstance(_evaluation_status, Unset):
190
+ evaluation_status = UNSET
191
+ else:
192
+ evaluation_status = EvaluationStatusEnum(_evaluation_status)
193
+
194
+ evaluation_notes = d.pop("evaluation_notes", UNSET)
195
+
196
+ evaluation_metrics = d.pop("evaluation_metrics", UNSET)
197
+
198
+ agent_specific_data = d.pop("agent_specific_data", UNSET)
199
+
200
+ result_request = cls(
201
+ run=run,
202
+ prompt=prompt,
203
+ request_payload=request_payload,
204
+ response_status_code=response_status_code,
205
+ response_headers=response_headers,
206
+ response_body=response_body,
207
+ latency_ms=latency_ms,
208
+ detected_tool_calls=detected_tool_calls,
209
+ evaluation_status=evaluation_status,
210
+ evaluation_notes=evaluation_notes,
211
+ evaluation_metrics=evaluation_metrics,
212
+ agent_specific_data=agent_specific_data,
213
+ )
214
+
215
+ result_request.additional_properties = d
216
+ return result_request
217
+
218
+ @property
219
+ def additional_keys(self) -> list[str]:
220
+ return list(self.additional_properties.keys())
221
+
222
+ def __getitem__(self, key: str) -> Any:
223
+ return self.additional_properties[key]
224
+
225
+ def __setitem__(self, key: str, value: Any) -> None:
226
+ self.additional_properties[key] = value
227
+
228
+ def __delitem__(self, key: str) -> None:
229
+ del self.additional_properties[key]
230
+
231
+ def __contains__(self, key: str) -> bool:
232
+ return key in self.additional_properties
@@ -0,0 +1,233 @@
1
+ import datetime
2
+ from collections.abc import Mapping
3
+ from typing import TYPE_CHECKING, Any, TypeVar, Union, cast
4
+ from uuid import UUID
5
+
6
+ from attrs import define as _attrs_define
7
+ from attrs import field as _attrs_field
8
+ from dateutil.parser import isoparse
9
+
10
+ from ..models.status_enum import StatusEnum
11
+ from ..types import UNSET, Unset
12
+
13
+ if TYPE_CHECKING:
14
+ from ..models.result import Result
15
+
16
+
17
+ T = TypeVar("T", bound="Run")
18
+
19
+
20
+ @_attrs_define
21
+ class Run:
22
+ """Serializer for the Run model, used for both input and output.
23
+
24
+ Attributes:
25
+ id (UUID):
26
+ agent (UUID):
27
+ agent_name (str):
28
+ owner (Union[None, int]):
29
+ owner_username (Union[None, str]):
30
+ organization (UUID):
31
+ organization_name (str):
32
+ timestamp (datetime.datetime):
33
+ is_client_executed (bool): Indicates if the run was initiated via an Attack by a client application.
34
+ results (list['Result']):
35
+ attack (Union[None, UUID, Unset]): The Attack this run is an instance of, if applicable.
36
+ run_config (Union[Unset, Any]): JSON containing specific settings for this run. If linked to an Attack, this
37
+ might be a copy or subset of its configuration.
38
+ status (Union[Unset, StatusEnum]): * `PENDING` - Pending
39
+ * `RUNNING` - Running
40
+ * `COMPLETED` - Completed
41
+ * `FAILED` - Failed
42
+ * `CANCELLED` - Cancelled
43
+ run_notes (Union[Unset, str]):
44
+ """
45
+
46
+ id: UUID
47
+ agent: UUID
48
+ agent_name: str
49
+ owner: Union[None, int]
50
+ owner_username: Union[None, str]
51
+ organization: UUID
52
+ organization_name: str
53
+ timestamp: datetime.datetime
54
+ is_client_executed: bool
55
+ results: list["Result"]
56
+ attack: Union[None, UUID, Unset] = UNSET
57
+ run_config: Union[Unset, Any] = UNSET
58
+ status: Union[Unset, StatusEnum] = UNSET
59
+ run_notes: Union[Unset, str] = UNSET
60
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
61
+
62
+ def to_dict(self) -> dict[str, Any]:
63
+ id = str(self.id)
64
+
65
+ agent = str(self.agent)
66
+
67
+ agent_name = self.agent_name
68
+
69
+ owner: Union[None, int]
70
+ owner = self.owner
71
+
72
+ owner_username: Union[None, str]
73
+ owner_username = self.owner_username
74
+
75
+ organization = str(self.organization)
76
+
77
+ organization_name = self.organization_name
78
+
79
+ timestamp = self.timestamp.isoformat()
80
+
81
+ is_client_executed = self.is_client_executed
82
+
83
+ results = []
84
+ for results_item_data in self.results:
85
+ results_item = results_item_data.to_dict()
86
+ results.append(results_item)
87
+
88
+ attack: Union[None, Unset, str]
89
+ if isinstance(self.attack, Unset):
90
+ attack = UNSET
91
+ elif isinstance(self.attack, UUID):
92
+ attack = str(self.attack)
93
+ else:
94
+ attack = self.attack
95
+
96
+ run_config = self.run_config
97
+
98
+ status: Union[Unset, str] = UNSET
99
+ if not isinstance(self.status, Unset):
100
+ status = self.status.value
101
+
102
+ run_notes = self.run_notes
103
+
104
+ field_dict: dict[str, Any] = {}
105
+ field_dict.update(self.additional_properties)
106
+ field_dict.update(
107
+ {
108
+ "id": id,
109
+ "agent": agent,
110
+ "agent_name": agent_name,
111
+ "owner": owner,
112
+ "owner_username": owner_username,
113
+ "organization": organization,
114
+ "organization_name": organization_name,
115
+ "timestamp": timestamp,
116
+ "is_client_executed": is_client_executed,
117
+ "results": results,
118
+ }
119
+ )
120
+ if attack is not UNSET:
121
+ field_dict["attack"] = attack
122
+ if run_config is not UNSET:
123
+ field_dict["run_config"] = run_config
124
+ if status is not UNSET:
125
+ field_dict["status"] = status
126
+ if run_notes is not UNSET:
127
+ field_dict["run_notes"] = run_notes
128
+
129
+ return field_dict
130
+
131
+ @classmethod
132
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
133
+ from ..models.result import Result
134
+
135
+ d = dict(src_dict)
136
+ id = UUID(d.pop("id"))
137
+
138
+ agent = UUID(d.pop("agent"))
139
+
140
+ agent_name = d.pop("agent_name")
141
+
142
+ def _parse_owner(data: object) -> Union[None, int]:
143
+ if data is None:
144
+ return data
145
+ return cast(Union[None, int], data)
146
+
147
+ owner = _parse_owner(d.pop("owner"))
148
+
149
+ def _parse_owner_username(data: object) -> Union[None, str]:
150
+ if data is None:
151
+ return data
152
+ return cast(Union[None, str], data)
153
+
154
+ owner_username = _parse_owner_username(d.pop("owner_username"))
155
+
156
+ organization = UUID(d.pop("organization"))
157
+
158
+ organization_name = d.pop("organization_name")
159
+
160
+ timestamp = isoparse(d.pop("timestamp"))
161
+
162
+ is_client_executed = d.pop("is_client_executed")
163
+
164
+ results = []
165
+ _results = d.pop("results")
166
+ for results_item_data in _results:
167
+ results_item = Result.from_dict(results_item_data)
168
+
169
+ results.append(results_item)
170
+
171
+ def _parse_attack(data: object) -> Union[None, UUID, Unset]:
172
+ if data is None:
173
+ return data
174
+ if isinstance(data, Unset):
175
+ return data
176
+ try:
177
+ if not isinstance(data, str):
178
+ raise TypeError()
179
+ attack_type_0 = UUID(data)
180
+
181
+ return attack_type_0
182
+ except: # noqa: E722
183
+ pass
184
+ return cast(Union[None, UUID, Unset], data)
185
+
186
+ attack = _parse_attack(d.pop("attack", UNSET))
187
+
188
+ run_config = d.pop("run_config", UNSET)
189
+
190
+ _status = d.pop("status", UNSET)
191
+ status: Union[Unset, StatusEnum]
192
+ if isinstance(_status, Unset):
193
+ status = UNSET
194
+ else:
195
+ status = StatusEnum(_status)
196
+
197
+ run_notes = d.pop("run_notes", UNSET)
198
+
199
+ run = cls(
200
+ id=id,
201
+ agent=agent,
202
+ agent_name=agent_name,
203
+ owner=owner,
204
+ owner_username=owner_username,
205
+ organization=organization,
206
+ organization_name=organization_name,
207
+ timestamp=timestamp,
208
+ is_client_executed=is_client_executed,
209
+ results=results,
210
+ attack=attack,
211
+ run_config=run_config,
212
+ status=status,
213
+ run_notes=run_notes,
214
+ )
215
+
216
+ run.additional_properties = d
217
+ return run
218
+
219
+ @property
220
+ def additional_keys(self) -> list[str]:
221
+ return list(self.additional_properties.keys())
222
+
223
+ def __getitem__(self, key: str) -> Any:
224
+ return self.additional_properties[key]
225
+
226
+ def __setitem__(self, key: str, value: Any) -> None:
227
+ self.additional_properties[key] = value
228
+
229
+ def __delitem__(self, key: str) -> None:
230
+ del self.additional_properties[key]
231
+
232
+ def __contains__(self, key: str) -> bool:
233
+ return key in self.additional_properties
@@ -0,0 +1,12 @@
1
+ from enum import Enum
2
+
3
+
4
+ class RunListStatus(str, Enum):
5
+ CANCELLED = "CANCELLED"
6
+ COMPLETED = "COMPLETED"
7
+ FAILED = "FAILED"
8
+ PENDING = "PENDING"
9
+ RUNNING = "RUNNING"
10
+
11
+ def __str__(self) -> str:
12
+ return str(self.value)
@@ -0,0 +1,133 @@
1
+ from collections.abc import Mapping
2
+ from typing import Any, TypeVar, Union, cast
3
+ from uuid import UUID
4
+
5
+ from attrs import define as _attrs_define
6
+ from attrs import field as _attrs_field
7
+
8
+ from ..models.status_enum import StatusEnum
9
+ from ..types import UNSET, Unset
10
+
11
+ T = TypeVar("T", bound="RunRequest")
12
+
13
+
14
+ @_attrs_define
15
+ class RunRequest:
16
+ """Serializer for the Run model, used for both input and output.
17
+
18
+ Attributes:
19
+ agent (UUID):
20
+ attack (Union[None, UUID, Unset]): The Attack this run is an instance of, if applicable.
21
+ run_config (Union[Unset, Any]): JSON containing specific settings for this run. If linked to an Attack, this
22
+ might be a copy or subset of its configuration.
23
+ status (Union[Unset, StatusEnum]): * `PENDING` - Pending
24
+ * `RUNNING` - Running
25
+ * `COMPLETED` - Completed
26
+ * `FAILED` - Failed
27
+ * `CANCELLED` - Cancelled
28
+ run_notes (Union[Unset, str]):
29
+ """
30
+
31
+ agent: UUID
32
+ attack: Union[None, UUID, Unset] = UNSET
33
+ run_config: Union[Unset, Any] = UNSET
34
+ status: Union[Unset, StatusEnum] = UNSET
35
+ run_notes: Union[Unset, str] = UNSET
36
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
37
+
38
+ def to_dict(self) -> dict[str, Any]:
39
+ agent = str(self.agent)
40
+
41
+ attack: Union[None, Unset, str]
42
+ if isinstance(self.attack, Unset):
43
+ attack = UNSET
44
+ elif isinstance(self.attack, UUID):
45
+ attack = str(self.attack)
46
+ else:
47
+ attack = self.attack
48
+
49
+ run_config = self.run_config
50
+
51
+ status: Union[Unset, str] = UNSET
52
+ if not isinstance(self.status, Unset):
53
+ status = self.status.value
54
+
55
+ run_notes = self.run_notes
56
+
57
+ field_dict: dict[str, Any] = {}
58
+ field_dict.update(self.additional_properties)
59
+ field_dict.update(
60
+ {
61
+ "agent": agent,
62
+ }
63
+ )
64
+ if attack is not UNSET:
65
+ field_dict["attack"] = attack
66
+ if run_config is not UNSET:
67
+ field_dict["run_config"] = run_config
68
+ if status is not UNSET:
69
+ field_dict["status"] = status
70
+ if run_notes is not UNSET:
71
+ field_dict["run_notes"] = run_notes
72
+
73
+ return field_dict
74
+
75
+ @classmethod
76
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
77
+ d = dict(src_dict)
78
+ agent = UUID(d.pop("agent"))
79
+
80
+ def _parse_attack(data: object) -> Union[None, UUID, Unset]:
81
+ if data is None:
82
+ return data
83
+ if isinstance(data, Unset):
84
+ return data
85
+ try:
86
+ if not isinstance(data, str):
87
+ raise TypeError()
88
+ attack_type_0 = UUID(data)
89
+
90
+ return attack_type_0
91
+ except: # noqa: E722
92
+ pass
93
+ return cast(Union[None, UUID, Unset], data)
94
+
95
+ attack = _parse_attack(d.pop("attack", UNSET))
96
+
97
+ run_config = d.pop("run_config", UNSET)
98
+
99
+ _status = d.pop("status", UNSET)
100
+ status: Union[Unset, StatusEnum]
101
+ if isinstance(_status, Unset):
102
+ status = UNSET
103
+ else:
104
+ status = StatusEnum(_status)
105
+
106
+ run_notes = d.pop("run_notes", UNSET)
107
+
108
+ run_request = cls(
109
+ agent=agent,
110
+ attack=attack,
111
+ run_config=run_config,
112
+ status=status,
113
+ run_notes=run_notes,
114
+ )
115
+
116
+ run_request.additional_properties = d
117
+ return run_request
118
+
119
+ @property
120
+ def additional_keys(self) -> list[str]:
121
+ return list(self.additional_properties.keys())
122
+
123
+ def __getitem__(self, key: str) -> Any:
124
+ return self.additional_properties[key]
125
+
126
+ def __setitem__(self, key: str, value: Any) -> None:
127
+ self.additional_properties[key] = value
128
+
129
+ def __delitem__(self, key: str) -> None:
130
+ del self.additional_properties[key]
131
+
132
+ def __contains__(self, key: str) -> bool:
133
+ return key in self.additional_properties
@@ -0,0 +1,12 @@
1
+ from enum import Enum
2
+
3
+
4
+ class StatusEnum(str, Enum):
5
+ CANCELLED = "CANCELLED"
6
+ COMPLETED = "COMPLETED"
7
+ FAILED = "FAILED"
8
+ PENDING = "PENDING"
9
+ RUNNING = "RUNNING"
10
+
11
+ def __str__(self) -> str:
12
+ return str(self.value)
@@ -0,0 +1,14 @@
1
+ from enum import Enum
2
+
3
+
4
+ class StepTypeEnum(str, Enum):
5
+ A2A_COMM = "A2A_COMM"
6
+ AGENT_RESPONSE_CHUNK = "AGENT_RESPONSE_CHUNK"
7
+ AGENT_THOUGHT = "AGENT_THOUGHT"
8
+ MCP_STEP = "MCP_STEP"
9
+ OTHER = "OTHER"
10
+ TOOL_CALL = "TOOL_CALL"
11
+ TOOL_RESPONSE = "TOOL_RESPONSE"
12
+
13
+ def __str__(self) -> str:
14
+ return str(self.value)