hackagent 0.1.0__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 (117) hide show
  1. hackagent/__init__.py +23 -0
  2. hackagent/agent.py +193 -0
  3. hackagent/api/__init__.py +1 -0
  4. hackagent/api/agent/__init__.py +1 -0
  5. hackagent/api/agent/agent_create.py +340 -0
  6. hackagent/api/agent/agent_destroy.py +136 -0
  7. hackagent/api/agent/agent_list.py +234 -0
  8. hackagent/api/agent/agent_partial_update.py +354 -0
  9. hackagent/api/agent/agent_retrieve.py +227 -0
  10. hackagent/api/agent/agent_update.py +354 -0
  11. hackagent/api/attack/__init__.py +1 -0
  12. hackagent/api/attack/attack_create.py +264 -0
  13. hackagent/api/attack/attack_destroy.py +140 -0
  14. hackagent/api/attack/attack_list.py +242 -0
  15. hackagent/api/attack/attack_partial_update.py +278 -0
  16. hackagent/api/attack/attack_retrieve.py +235 -0
  17. hackagent/api/attack/attack_update.py +278 -0
  18. hackagent/api/key/__init__.py +1 -0
  19. hackagent/api/key/key_create.py +168 -0
  20. hackagent/api/key/key_destroy.py +97 -0
  21. hackagent/api/key/key_list.py +158 -0
  22. hackagent/api/key/key_retrieve.py +150 -0
  23. hackagent/api/prompt/__init__.py +1 -0
  24. hackagent/api/prompt/prompt_create.py +160 -0
  25. hackagent/api/prompt/prompt_destroy.py +98 -0
  26. hackagent/api/prompt/prompt_list.py +173 -0
  27. hackagent/api/prompt/prompt_partial_update.py +174 -0
  28. hackagent/api/prompt/prompt_retrieve.py +151 -0
  29. hackagent/api/prompt/prompt_update.py +174 -0
  30. hackagent/api/result/__init__.py +1 -0
  31. hackagent/api/result/result_create.py +160 -0
  32. hackagent/api/result/result_destroy.py +98 -0
  33. hackagent/api/result/result_list.py +233 -0
  34. hackagent/api/result/result_partial_update.py +178 -0
  35. hackagent/api/result/result_retrieve.py +151 -0
  36. hackagent/api/result/result_trace_create.py +178 -0
  37. hackagent/api/result/result_update.py +174 -0
  38. hackagent/api/run/__init__.py +1 -0
  39. hackagent/api/run/run_create.py +172 -0
  40. hackagent/api/run/run_destroy.py +104 -0
  41. hackagent/api/run/run_list.py +260 -0
  42. hackagent/api/run/run_partial_update.py +186 -0
  43. hackagent/api/run/run_result_create.py +178 -0
  44. hackagent/api/run/run_retrieve.py +163 -0
  45. hackagent/api/run/run_run_tests_create.py +172 -0
  46. hackagent/api/run/run_update.py +186 -0
  47. hackagent/attacks/AdvPrefix/README.md +7 -0
  48. hackagent/attacks/AdvPrefix/__init__.py +0 -0
  49. hackagent/attacks/AdvPrefix/completer.py +438 -0
  50. hackagent/attacks/AdvPrefix/config.py +59 -0
  51. hackagent/attacks/AdvPrefix/preprocessing.py +521 -0
  52. hackagent/attacks/AdvPrefix/scorer.py +259 -0
  53. hackagent/attacks/AdvPrefix/scorer_parser.py +498 -0
  54. hackagent/attacks/AdvPrefix/selector.py +246 -0
  55. hackagent/attacks/AdvPrefix/step1_generate.py +324 -0
  56. hackagent/attacks/AdvPrefix/step4_compute_ce.py +293 -0
  57. hackagent/attacks/AdvPrefix/step6_get_completions.py +387 -0
  58. hackagent/attacks/AdvPrefix/step7_evaluate_responses.py +289 -0
  59. hackagent/attacks/AdvPrefix/step8_aggregate_evaluations.py +177 -0
  60. hackagent/attacks/AdvPrefix/step9_select_prefixes.py +59 -0
  61. hackagent/attacks/AdvPrefix/utils.py +192 -0
  62. hackagent/attacks/__init__.py +6 -0
  63. hackagent/attacks/advprefix.py +1136 -0
  64. hackagent/attacks/base.py +50 -0
  65. hackagent/attacks/strategies.py +539 -0
  66. hackagent/branding.py +143 -0
  67. hackagent/client.py +328 -0
  68. hackagent/errors.py +31 -0
  69. hackagent/logger.py +67 -0
  70. hackagent/models/__init__.py +71 -0
  71. hackagent/models/agent.py +240 -0
  72. hackagent/models/agent_request.py +169 -0
  73. hackagent/models/agent_type_enum.py +12 -0
  74. hackagent/models/attack.py +154 -0
  75. hackagent/models/attack_request.py +82 -0
  76. hackagent/models/evaluation_status_enum.py +14 -0
  77. hackagent/models/organization_minimal.py +68 -0
  78. hackagent/models/paginated_agent_list.py +123 -0
  79. hackagent/models/paginated_attack_list.py +123 -0
  80. hackagent/models/paginated_prompt_list.py +123 -0
  81. hackagent/models/paginated_result_list.py +123 -0
  82. hackagent/models/paginated_run_list.py +123 -0
  83. hackagent/models/paginated_user_api_key_list.py +123 -0
  84. hackagent/models/patched_agent_request.py +176 -0
  85. hackagent/models/patched_attack_request.py +92 -0
  86. hackagent/models/patched_prompt_request.py +162 -0
  87. hackagent/models/patched_result_request.py +237 -0
  88. hackagent/models/patched_run_request.py +138 -0
  89. hackagent/models/prompt.py +226 -0
  90. hackagent/models/prompt_request.py +155 -0
  91. hackagent/models/result.py +294 -0
  92. hackagent/models/result_list_evaluation_status.py +14 -0
  93. hackagent/models/result_request.py +232 -0
  94. hackagent/models/run.py +233 -0
  95. hackagent/models/run_list_status.py +12 -0
  96. hackagent/models/run_request.py +133 -0
  97. hackagent/models/status_enum.py +12 -0
  98. hackagent/models/step_type_enum.py +14 -0
  99. hackagent/models/trace.py +121 -0
  100. hackagent/models/trace_request.py +94 -0
  101. hackagent/models/user_api_key.py +201 -0
  102. hackagent/models/user_api_key_request.py +73 -0
  103. hackagent/models/user_profile_minimal.py +76 -0
  104. hackagent/py.typed +1 -0
  105. hackagent/router/__init__.py +11 -0
  106. hackagent/router/adapters/__init__.py +5 -0
  107. hackagent/router/adapters/google_adk.py +658 -0
  108. hackagent/router/adapters/litellm_adapter.py +290 -0
  109. hackagent/router/base.py +48 -0
  110. hackagent/router/router.py +753 -0
  111. hackagent/types.py +46 -0
  112. hackagent/utils.py +61 -0
  113. hackagent/vulnerabilities/__init__.py +0 -0
  114. hackagent-0.1.0.dist-info/LICENSE +202 -0
  115. hackagent-0.1.0.dist-info/METADATA +173 -0
  116. hackagent-0.1.0.dist-info/RECORD +117 -0
  117. hackagent-0.1.0.dist-info/WHEEL +4 -0
@@ -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)
@@ -0,0 +1,121 @@
1
+ import datetime
2
+ from collections.abc import Mapping
3
+ from typing import Any, TypeVar, Union
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.step_type_enum import StepTypeEnum
11
+ from ..types import UNSET, Unset
12
+
13
+ T = TypeVar("T", bound="Trace")
14
+
15
+
16
+ @_attrs_define
17
+ class Trace:
18
+ """Serializer for the Trace model.
19
+
20
+ Attributes:
21
+ id (int):
22
+ result (UUID):
23
+ sequence (int):
24
+ timestamp (datetime.datetime):
25
+ step_type (Union[Unset, StepTypeEnum]): * `TOOL_CALL` - Tool Call
26
+ * `TOOL_RESPONSE` - Tool Response
27
+ * `AGENT_THOUGHT` - Agent Thought/Reasoning
28
+ * `AGENT_RESPONSE_CHUNK` - Agent Response Chunk
29
+ * `OTHER` - Other
30
+ * `MCP_STEP` - Multi-Context Prompting Step
31
+ * `A2A_COMM` - Agent-to-Agent Communication
32
+ content (Union[Unset, Any]):
33
+ """
34
+
35
+ id: int
36
+ result: UUID
37
+ sequence: int
38
+ timestamp: datetime.datetime
39
+ step_type: Union[Unset, StepTypeEnum] = UNSET
40
+ content: Union[Unset, Any] = UNSET
41
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
42
+
43
+ def to_dict(self) -> dict[str, Any]:
44
+ id = self.id
45
+
46
+ result = str(self.result)
47
+
48
+ sequence = self.sequence
49
+
50
+ timestamp = self.timestamp.isoformat()
51
+
52
+ step_type: Union[Unset, str] = UNSET
53
+ if not isinstance(self.step_type, Unset):
54
+ step_type = self.step_type.value
55
+
56
+ content = self.content
57
+
58
+ field_dict: dict[str, Any] = {}
59
+ field_dict.update(self.additional_properties)
60
+ field_dict.update(
61
+ {
62
+ "id": id,
63
+ "result": result,
64
+ "sequence": sequence,
65
+ "timestamp": timestamp,
66
+ }
67
+ )
68
+ if step_type is not UNSET:
69
+ field_dict["step_type"] = step_type
70
+ if content is not UNSET:
71
+ field_dict["content"] = content
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
+ id = d.pop("id")
79
+
80
+ result = UUID(d.pop("result"))
81
+
82
+ sequence = d.pop("sequence")
83
+
84
+ timestamp = isoparse(d.pop("timestamp"))
85
+
86
+ _step_type = d.pop("step_type", UNSET)
87
+ step_type: Union[Unset, StepTypeEnum]
88
+ if isinstance(_step_type, Unset):
89
+ step_type = UNSET
90
+ else:
91
+ step_type = StepTypeEnum(_step_type)
92
+
93
+ content = d.pop("content", UNSET)
94
+
95
+ trace = cls(
96
+ id=id,
97
+ result=result,
98
+ sequence=sequence,
99
+ timestamp=timestamp,
100
+ step_type=step_type,
101
+ content=content,
102
+ )
103
+
104
+ trace.additional_properties = d
105
+ return trace
106
+
107
+ @property
108
+ def additional_keys(self) -> list[str]:
109
+ return list(self.additional_properties.keys())
110
+
111
+ def __getitem__(self, key: str) -> Any:
112
+ return self.additional_properties[key]
113
+
114
+ def __setitem__(self, key: str, value: Any) -> None:
115
+ self.additional_properties[key] = value
116
+
117
+ def __delitem__(self, key: str) -> None:
118
+ del self.additional_properties[key]
119
+
120
+ def __contains__(self, key: str) -> bool:
121
+ return key in self.additional_properties
@@ -0,0 +1,94 @@
1
+ from collections.abc import Mapping
2
+ from typing import Any, TypeVar, Union
3
+
4
+ from attrs import define as _attrs_define
5
+ from attrs import field as _attrs_field
6
+
7
+ from ..models.step_type_enum import StepTypeEnum
8
+ from ..types import UNSET, Unset
9
+
10
+ T = TypeVar("T", bound="TraceRequest")
11
+
12
+
13
+ @_attrs_define
14
+ class TraceRequest:
15
+ """Serializer for the Trace model.
16
+
17
+ Attributes:
18
+ sequence (int):
19
+ step_type (Union[Unset, StepTypeEnum]): * `TOOL_CALL` - Tool Call
20
+ * `TOOL_RESPONSE` - Tool Response
21
+ * `AGENT_THOUGHT` - Agent Thought/Reasoning
22
+ * `AGENT_RESPONSE_CHUNK` - Agent Response Chunk
23
+ * `OTHER` - Other
24
+ * `MCP_STEP` - Multi-Context Prompting Step
25
+ * `A2A_COMM` - Agent-to-Agent Communication
26
+ content (Union[Unset, Any]):
27
+ """
28
+
29
+ sequence: int
30
+ step_type: Union[Unset, StepTypeEnum] = UNSET
31
+ content: Union[Unset, Any] = UNSET
32
+ additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
33
+
34
+ def to_dict(self) -> dict[str, Any]:
35
+ sequence = self.sequence
36
+
37
+ step_type: Union[Unset, str] = UNSET
38
+ if not isinstance(self.step_type, Unset):
39
+ step_type = self.step_type.value
40
+
41
+ content = self.content
42
+
43
+ field_dict: dict[str, Any] = {}
44
+ field_dict.update(self.additional_properties)
45
+ field_dict.update(
46
+ {
47
+ "sequence": sequence,
48
+ }
49
+ )
50
+ if step_type is not UNSET:
51
+ field_dict["step_type"] = step_type
52
+ if content is not UNSET:
53
+ field_dict["content"] = content
54
+
55
+ return field_dict
56
+
57
+ @classmethod
58
+ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
59
+ d = dict(src_dict)
60
+ sequence = d.pop("sequence")
61
+
62
+ _step_type = d.pop("step_type", UNSET)
63
+ step_type: Union[Unset, StepTypeEnum]
64
+ if isinstance(_step_type, Unset):
65
+ step_type = UNSET
66
+ else:
67
+ step_type = StepTypeEnum(_step_type)
68
+
69
+ content = d.pop("content", UNSET)
70
+
71
+ trace_request = cls(
72
+ sequence=sequence,
73
+ step_type=step_type,
74
+ content=content,
75
+ )
76
+
77
+ trace_request.additional_properties = d
78
+ return trace_request
79
+
80
+ @property
81
+ def additional_keys(self) -> list[str]:
82
+ return list(self.additional_properties.keys())
83
+
84
+ def __getitem__(self, key: str) -> Any:
85
+ return self.additional_properties[key]
86
+
87
+ def __setitem__(self, key: str, value: Any) -> None:
88
+ self.additional_properties[key] = value
89
+
90
+ def __delitem__(self, key: str) -> None:
91
+ del self.additional_properties[key]
92
+
93
+ def __contains__(self, key: str) -> bool:
94
+ return key in self.additional_properties