sondera-harness 0.6.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.
- sondera/__init__.py +111 -0
- sondera/__main__.py +4 -0
- sondera/adk/__init__.py +3 -0
- sondera/adk/analyze.py +222 -0
- sondera/adk/plugin.py +387 -0
- sondera/cli.py +22 -0
- sondera/exceptions.py +167 -0
- sondera/harness/__init__.py +6 -0
- sondera/harness/abc.py +102 -0
- sondera/harness/cedar/__init__.py +0 -0
- sondera/harness/cedar/harness.py +363 -0
- sondera/harness/cedar/schema.py +225 -0
- sondera/harness/sondera/__init__.py +0 -0
- sondera/harness/sondera/_grpc.py +354 -0
- sondera/harness/sondera/harness.py +890 -0
- sondera/langgraph/__init__.py +15 -0
- sondera/langgraph/analyze.py +543 -0
- sondera/langgraph/exceptions.py +19 -0
- sondera/langgraph/graph.py +210 -0
- sondera/langgraph/middleware.py +454 -0
- sondera/proto/google/protobuf/any_pb2.py +37 -0
- sondera/proto/google/protobuf/any_pb2.pyi +14 -0
- sondera/proto/google/protobuf/any_pb2_grpc.py +24 -0
- sondera/proto/google/protobuf/duration_pb2.py +37 -0
- sondera/proto/google/protobuf/duration_pb2.pyi +14 -0
- sondera/proto/google/protobuf/duration_pb2_grpc.py +24 -0
- sondera/proto/google/protobuf/empty_pb2.py +37 -0
- sondera/proto/google/protobuf/empty_pb2.pyi +9 -0
- sondera/proto/google/protobuf/empty_pb2_grpc.py +24 -0
- sondera/proto/google/protobuf/struct_pb2.py +47 -0
- sondera/proto/google/protobuf/struct_pb2.pyi +49 -0
- sondera/proto/google/protobuf/struct_pb2_grpc.py +24 -0
- sondera/proto/google/protobuf/timestamp_pb2.py +37 -0
- sondera/proto/google/protobuf/timestamp_pb2.pyi +14 -0
- sondera/proto/google/protobuf/timestamp_pb2_grpc.py +24 -0
- sondera/proto/google/protobuf/wrappers_pb2.py +53 -0
- sondera/proto/google/protobuf/wrappers_pb2.pyi +59 -0
- sondera/proto/google/protobuf/wrappers_pb2_grpc.py +24 -0
- sondera/proto/sondera/__init__.py +0 -0
- sondera/proto/sondera/core/__init__.py +0 -0
- sondera/proto/sondera/core/v1/__init__.py +0 -0
- sondera/proto/sondera/core/v1/primitives_pb2.py +88 -0
- sondera/proto/sondera/core/v1/primitives_pb2.pyi +259 -0
- sondera/proto/sondera/core/v1/primitives_pb2_grpc.py +24 -0
- sondera/proto/sondera/harness/__init__.py +0 -0
- sondera/proto/sondera/harness/v1/__init__.py +0 -0
- sondera/proto/sondera/harness/v1/harness_pb2.py +81 -0
- sondera/proto/sondera/harness/v1/harness_pb2.pyi +192 -0
- sondera/proto/sondera/harness/v1/harness_pb2_grpc.py +498 -0
- sondera/py.typed +0 -0
- sondera/settings.py +20 -0
- sondera/strands/__init__.py +5 -0
- sondera/strands/analyze.py +244 -0
- sondera/strands/harness.py +333 -0
- sondera/tui/__init__.py +0 -0
- sondera/tui/app.py +309 -0
- sondera/tui/screens/__init__.py +5 -0
- sondera/tui/screens/adjudication.py +184 -0
- sondera/tui/screens/agent.py +158 -0
- sondera/tui/screens/trajectory.py +158 -0
- sondera/tui/widgets/__init__.py +23 -0
- sondera/tui/widgets/agent_card.py +94 -0
- sondera/tui/widgets/agent_list.py +73 -0
- sondera/tui/widgets/recent_adjudications.py +52 -0
- sondera/tui/widgets/recent_trajectories.py +54 -0
- sondera/tui/widgets/summary.py +57 -0
- sondera/tui/widgets/tool_card.py +33 -0
- sondera/tui/widgets/violation_panel.py +72 -0
- sondera/tui/widgets/violations_list.py +78 -0
- sondera/tui/widgets/violations_summary.py +104 -0
- sondera/types.py +346 -0
- sondera_harness-0.6.0.dist-info/METADATA +323 -0
- sondera_harness-0.6.0.dist-info/RECORD +77 -0
- sondera_harness-0.6.0.dist-info/WHEEL +5 -0
- sondera_harness-0.6.0.dist-info/entry_points.txt +2 -0
- sondera_harness-0.6.0.dist-info/licenses/LICENSE +21 -0
- sondera_harness-0.6.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
from datetime import UTC, datetime
|
|
2
|
+
|
|
3
|
+
from google.protobuf import struct_pb2
|
|
4
|
+
from google.protobuf.json_format import MessageToDict
|
|
5
|
+
|
|
6
|
+
from sondera.proto.sondera.core.v1 import primitives_pb2
|
|
7
|
+
from sondera.proto.sondera.harness.v1 import harness_pb2
|
|
8
|
+
from sondera.types import (
|
|
9
|
+
AdjudicatedStep,
|
|
10
|
+
AdjudicatedTrajectory,
|
|
11
|
+
Adjudication,
|
|
12
|
+
AdjudicationRecord,
|
|
13
|
+
Agent,
|
|
14
|
+
Content,
|
|
15
|
+
Decision,
|
|
16
|
+
Parameter,
|
|
17
|
+
PolicyAnnotation,
|
|
18
|
+
PolicyEngineMode,
|
|
19
|
+
PromptContent,
|
|
20
|
+
Role,
|
|
21
|
+
Stage,
|
|
22
|
+
Tool,
|
|
23
|
+
ToolRequestContent,
|
|
24
|
+
ToolResponseContent,
|
|
25
|
+
Trajectory,
|
|
26
|
+
TrajectoryStatus,
|
|
27
|
+
TrajectoryStep,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _convert_sdk_stage_to_pb(stage: Stage) -> primitives_pb2.Stage:
|
|
32
|
+
"""Convert SDK Stage to protobuf Stage."""
|
|
33
|
+
stage_map = {
|
|
34
|
+
Stage.PRE_RUN: primitives_pb2.STAGE_PRE_RUN,
|
|
35
|
+
Stage.PRE_MODEL: primitives_pb2.STAGE_PRE_MODEL,
|
|
36
|
+
Stage.POST_MODEL: primitives_pb2.STAGE_POST_MODEL,
|
|
37
|
+
Stage.PRE_TOOL: primitives_pb2.STAGE_PRE_TOOL,
|
|
38
|
+
Stage.POST_TOOL: primitives_pb2.STAGE_POST_TOOL,
|
|
39
|
+
Stage.POST_RUN: primitives_pb2.STAGE_POST_RUN,
|
|
40
|
+
}
|
|
41
|
+
return stage_map[stage]
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _convert_sdk_role_to_pb(role: Role) -> primitives_pb2.Role:
|
|
45
|
+
"""Convert SDK Role to protobuf Role."""
|
|
46
|
+
role_map = {
|
|
47
|
+
Role.USER: primitives_pb2.ROLE_USER,
|
|
48
|
+
Role.MODEL: primitives_pb2.ROLE_MODEL,
|
|
49
|
+
Role.TOOL: primitives_pb2.ROLE_TOOL,
|
|
50
|
+
Role.SYSTEM: primitives_pb2.ROLE_SYSTEM,
|
|
51
|
+
}
|
|
52
|
+
return role_map[role]
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _convert_sdk_content_to_pb(content: Content) -> primitives_pb2.Content:
|
|
56
|
+
"""Convert SDK Content to protobuf Content."""
|
|
57
|
+
if isinstance(content, PromptContent):
|
|
58
|
+
return primitives_pb2.Content(prompt=primitives_pb2.Prompt(text=content.text))
|
|
59
|
+
elif isinstance(content, ToolRequestContent):
|
|
60
|
+
# Convert Python dict to protobuf Value
|
|
61
|
+
value = struct_pb2.Value()
|
|
62
|
+
value.struct_value.update(content.args)
|
|
63
|
+
return primitives_pb2.Content(
|
|
64
|
+
tool_request=primitives_pb2.ToolRequest(tool_id=content.tool_id, args=value)
|
|
65
|
+
)
|
|
66
|
+
elif isinstance(content, ToolResponseContent):
|
|
67
|
+
# Convert Python dict to protobuf Value
|
|
68
|
+
value = struct_pb2.Value()
|
|
69
|
+
if isinstance(content.response, dict):
|
|
70
|
+
value.struct_value.update(content.response)
|
|
71
|
+
elif isinstance(content.response, list | tuple):
|
|
72
|
+
value.list_value.extend(content.response)
|
|
73
|
+
else:
|
|
74
|
+
value.string_value = str(content.response)
|
|
75
|
+
return primitives_pb2.Content(
|
|
76
|
+
tool_response=primitives_pb2.ToolResponse(
|
|
77
|
+
tool_id=content.tool_id, response=value
|
|
78
|
+
)
|
|
79
|
+
)
|
|
80
|
+
else:
|
|
81
|
+
raise ValueError(f"Unsupported content type: {type(content)}")
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def _convert_pb_adjudication_to_sdk(
|
|
85
|
+
adjudication: primitives_pb2.Adjudication,
|
|
86
|
+
) -> Adjudication:
|
|
87
|
+
"""Convert protobuf Adjudication to SDK Adjudication."""
|
|
88
|
+
# Convert decision
|
|
89
|
+
decision_map = {
|
|
90
|
+
primitives_pb2.DECISION_ALLOW: Decision.ALLOW,
|
|
91
|
+
primitives_pb2.DECISION_DENY: Decision.DENY,
|
|
92
|
+
primitives_pb2.DECISION_ESCALATE: Decision.ESCALATE,
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
# Convert annotations
|
|
96
|
+
annotations = [
|
|
97
|
+
PolicyAnnotation(
|
|
98
|
+
id=ann.id,
|
|
99
|
+
description=ann.description,
|
|
100
|
+
custom=dict(ann.custom),
|
|
101
|
+
)
|
|
102
|
+
for ann in adjudication.annotations
|
|
103
|
+
]
|
|
104
|
+
|
|
105
|
+
return Adjudication(
|
|
106
|
+
decision=decision_map[adjudication.decision],
|
|
107
|
+
reason=adjudication.reason,
|
|
108
|
+
annotations=annotations,
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def _convert_pb_agent_to_sdk(pb_agent: primitives_pb2.Agent) -> Agent:
|
|
113
|
+
"""Convert protobuf Agent to SDK Agent."""
|
|
114
|
+
tools = []
|
|
115
|
+
for pb_tool in pb_agent.tools:
|
|
116
|
+
params = [
|
|
117
|
+
Parameter(name=p.name, description=p.description, type=p.type)
|
|
118
|
+
for p in pb_tool.parameters
|
|
119
|
+
]
|
|
120
|
+
tools.append(
|
|
121
|
+
Tool(
|
|
122
|
+
id=None, # Protobuf Tool message doesn't have an id field
|
|
123
|
+
name=pb_tool.name,
|
|
124
|
+
description=pb_tool.description,
|
|
125
|
+
parameters=params,
|
|
126
|
+
response=pb_tool.response if pb_tool.response else None,
|
|
127
|
+
)
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
return Agent(
|
|
131
|
+
id=pb_agent.id,
|
|
132
|
+
provider_id=pb_agent.provider_id,
|
|
133
|
+
name=pb_agent.name,
|
|
134
|
+
description=pb_agent.description,
|
|
135
|
+
instruction=pb_agent.instruction,
|
|
136
|
+
tools=tools,
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def _convert_pb_trajectory_status_to_sdk(
|
|
141
|
+
pb_status: primitives_pb2.TrajectoryStatus,
|
|
142
|
+
) -> TrajectoryStatus:
|
|
143
|
+
"""Convert protobuf TrajectoryStatus to SDK TrajectoryStatus."""
|
|
144
|
+
status_map = {
|
|
145
|
+
primitives_pb2.TRAJECTORY_STATUS_UNSPECIFIED: TrajectoryStatus.UNKNOWN,
|
|
146
|
+
primitives_pb2.TRAJECTORY_STATUS_PENDING: TrajectoryStatus.PENDING,
|
|
147
|
+
primitives_pb2.TRAJECTORY_STATUS_RUNNING: TrajectoryStatus.RUNNING,
|
|
148
|
+
primitives_pb2.TRAJECTORY_STATUS_COMPLETED: TrajectoryStatus.COMPLETED,
|
|
149
|
+
primitives_pb2.TRAJECTORY_STATUS_SUSPENDED: TrajectoryStatus.SUSPENDED,
|
|
150
|
+
primitives_pb2.TRAJECTORY_STATUS_FAILED: TrajectoryStatus.FAILED,
|
|
151
|
+
}
|
|
152
|
+
return status_map[pb_status]
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def _convert_sdk_trajectory_status_to_pb(
|
|
156
|
+
status: TrajectoryStatus,
|
|
157
|
+
) -> primitives_pb2.TrajectoryStatus:
|
|
158
|
+
"""Convert SDK TrajectoryStatus to protobuf TrajectoryStatus."""
|
|
159
|
+
status_map = {
|
|
160
|
+
TrajectoryStatus.UNKNOWN: primitives_pb2.TRAJECTORY_STATUS_UNSPECIFIED,
|
|
161
|
+
TrajectoryStatus.PENDING: primitives_pb2.TRAJECTORY_STATUS_PENDING,
|
|
162
|
+
TrajectoryStatus.RUNNING: primitives_pb2.TRAJECTORY_STATUS_RUNNING,
|
|
163
|
+
TrajectoryStatus.COMPLETED: primitives_pb2.TRAJECTORY_STATUS_COMPLETED,
|
|
164
|
+
TrajectoryStatus.SUSPENDED: primitives_pb2.TRAJECTORY_STATUS_SUSPENDED,
|
|
165
|
+
TrajectoryStatus.FAILED: primitives_pb2.TRAJECTORY_STATUS_FAILED,
|
|
166
|
+
}
|
|
167
|
+
return status_map[status]
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def _convert_pb_stage_to_sdk(pb_stage: primitives_pb2.Stage) -> Stage:
|
|
171
|
+
"""Convert protobuf Stage to SDK Stage."""
|
|
172
|
+
stage_map = {
|
|
173
|
+
primitives_pb2.STAGE_PRE_RUN: Stage.PRE_RUN,
|
|
174
|
+
primitives_pb2.STAGE_PRE_MODEL: Stage.PRE_MODEL,
|
|
175
|
+
primitives_pb2.STAGE_POST_MODEL: Stage.POST_MODEL,
|
|
176
|
+
primitives_pb2.STAGE_PRE_TOOL: Stage.PRE_TOOL,
|
|
177
|
+
primitives_pb2.STAGE_POST_TOOL: Stage.POST_TOOL,
|
|
178
|
+
primitives_pb2.STAGE_POST_RUN: Stage.POST_RUN,
|
|
179
|
+
}
|
|
180
|
+
return stage_map[pb_stage]
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def _convert_pb_role_to_sdk(pb_role: primitives_pb2.Role) -> Role:
|
|
184
|
+
"""Convert protobuf Role to SDK Role."""
|
|
185
|
+
role_map = {
|
|
186
|
+
primitives_pb2.ROLE_USER: Role.USER,
|
|
187
|
+
primitives_pb2.ROLE_MODEL: Role.MODEL,
|
|
188
|
+
primitives_pb2.ROLE_TOOL: Role.TOOL,
|
|
189
|
+
primitives_pb2.ROLE_SYSTEM: Role.SYSTEM,
|
|
190
|
+
}
|
|
191
|
+
return role_map[pb_role]
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
def _convert_pb_content_to_sdk(pb_content: primitives_pb2.Content) -> Content:
|
|
195
|
+
"""Convert protobuf Content to SDK Content."""
|
|
196
|
+
if pb_content.HasField("prompt"):
|
|
197
|
+
return PromptContent(text=pb_content.prompt.text)
|
|
198
|
+
elif pb_content.HasField("tool_request"):
|
|
199
|
+
# Convert protobuf Value to Python dict
|
|
200
|
+
args = {}
|
|
201
|
+
if pb_content.tool_request.HasField("args"):
|
|
202
|
+
args = MessageToDict(
|
|
203
|
+
pb_content.tool_request.args, preserving_proto_field_name=True
|
|
204
|
+
)
|
|
205
|
+
if not isinstance(args, dict):
|
|
206
|
+
args = {}
|
|
207
|
+
return ToolRequestContent(tool_id=pb_content.tool_request.tool_id, args=args)
|
|
208
|
+
elif pb_content.HasField("tool_response"):
|
|
209
|
+
# Convert protobuf Value to Python value
|
|
210
|
+
response = MessageToDict(
|
|
211
|
+
pb_content.tool_response.response, preserving_proto_field_name=True
|
|
212
|
+
)
|
|
213
|
+
return ToolResponseContent(
|
|
214
|
+
tool_id=pb_content.tool_response.tool_id, response=response
|
|
215
|
+
)
|
|
216
|
+
else:
|
|
217
|
+
raise ValueError(
|
|
218
|
+
f"Unsupported protobuf content type: {pb_content.WhichOneof('content_type')}"
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def _convert_pb_trajectory_step_to_sdk(
|
|
223
|
+
pb_step: primitives_pb2.TrajectoryStep,
|
|
224
|
+
) -> TrajectoryStep:
|
|
225
|
+
"""Convert protobuf TrajectoryStep to SDK TrajectoryStep."""
|
|
226
|
+
created_at = (
|
|
227
|
+
datetime.fromtimestamp(pb_step.created_at.seconds, tz=UTC)
|
|
228
|
+
if pb_step.HasField("created_at")
|
|
229
|
+
else datetime.now(tz=UTC)
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
content = (
|
|
233
|
+
_convert_pb_content_to_sdk(pb_step.content)
|
|
234
|
+
if pb_step.HasField("content")
|
|
235
|
+
else None
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
return TrajectoryStep(
|
|
239
|
+
role=_convert_pb_role_to_sdk(pb_step.role),
|
|
240
|
+
stage=_convert_pb_stage_to_sdk(pb_step.stage),
|
|
241
|
+
content=content,
|
|
242
|
+
created_at=created_at,
|
|
243
|
+
state={}, # State is not in protobuf TrajectoryStep
|
|
244
|
+
context=None, # Context is not in protobuf TrajectoryStep
|
|
245
|
+
)
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
def _convert_pb_adjudicated_step_to_sdk(
|
|
249
|
+
pb_adjudicated_step: primitives_pb2.AdjudicatedStep,
|
|
250
|
+
) -> AdjudicatedStep:
|
|
251
|
+
"""Convert protobuf AdjudicatedStep to SDK AdjudicatedStep."""
|
|
252
|
+
# Convert the step
|
|
253
|
+
pb_step = pb_adjudicated_step.step if pb_adjudicated_step.HasField("step") else None
|
|
254
|
+
if pb_step is None:
|
|
255
|
+
raise ValueError("AdjudicatedStep must have a step field")
|
|
256
|
+
|
|
257
|
+
trajectory_step = _convert_pb_trajectory_step_to_sdk(pb_step)
|
|
258
|
+
|
|
259
|
+
# Convert adjudication
|
|
260
|
+
pb_adjudication = (
|
|
261
|
+
pb_adjudicated_step.adjudication
|
|
262
|
+
if pb_adjudicated_step.HasField("adjudication")
|
|
263
|
+
else None
|
|
264
|
+
)
|
|
265
|
+
if pb_adjudication is None:
|
|
266
|
+
raise ValueError("AdjudicatedStep must have an adjudication field")
|
|
267
|
+
adjudication = _convert_pb_adjudication_to_sdk(pb_adjudication)
|
|
268
|
+
|
|
269
|
+
# Default mode to GOVERN since protobuf doesn't have this field
|
|
270
|
+
# In practice, this should be set based on the policy engine configuration
|
|
271
|
+
mode = PolicyEngineMode.GOVERN
|
|
272
|
+
|
|
273
|
+
return AdjudicatedStep(mode=mode, adjudication=adjudication, step=trajectory_step)
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
def _convert_pb_trajectory_to_sdk(
|
|
277
|
+
pb_trajectory: primitives_pb2.Trajectory,
|
|
278
|
+
) -> Trajectory:
|
|
279
|
+
"""Convert protobuf Trajectory to SDK Trajectory."""
|
|
280
|
+
# Convert timestamps
|
|
281
|
+
created_at = (
|
|
282
|
+
datetime.fromtimestamp(pb_trajectory.created_at.seconds, tz=UTC)
|
|
283
|
+
if pb_trajectory.HasField("created_at")
|
|
284
|
+
else datetime.now(tz=UTC)
|
|
285
|
+
)
|
|
286
|
+
updated_at = (
|
|
287
|
+
datetime.fromtimestamp(pb_trajectory.updated_at.seconds, tz=UTC)
|
|
288
|
+
if pb_trajectory.HasField("updated_at")
|
|
289
|
+
else datetime.now(tz=UTC)
|
|
290
|
+
)
|
|
291
|
+
started_at = (
|
|
292
|
+
datetime.fromtimestamp(pb_trajectory.started_at.seconds, tz=UTC)
|
|
293
|
+
if pb_trajectory.HasField("started_at")
|
|
294
|
+
else None
|
|
295
|
+
)
|
|
296
|
+
ended_at = (
|
|
297
|
+
datetime.fromtimestamp(pb_trajectory.ended_at.seconds, tz=UTC)
|
|
298
|
+
if pb_trajectory.HasField("ended_at")
|
|
299
|
+
else None
|
|
300
|
+
)
|
|
301
|
+
|
|
302
|
+
# Convert metadata (protobuf map<string, Value> to dict)
|
|
303
|
+
metadata = {
|
|
304
|
+
key: MessageToDict(value, preserving_proto_field_name=True)
|
|
305
|
+
for key, value in pb_trajectory.metadata.items()
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
return Trajectory(
|
|
309
|
+
id=pb_trajectory.id,
|
|
310
|
+
agent_id=pb_trajectory.agent_id,
|
|
311
|
+
status=_convert_pb_trajectory_status_to_sdk(pb_trajectory.status),
|
|
312
|
+
metadata=metadata,
|
|
313
|
+
created_at=created_at,
|
|
314
|
+
updated_at=updated_at,
|
|
315
|
+
started_at=started_at,
|
|
316
|
+
ended_at=ended_at,
|
|
317
|
+
steps=[], # Steps are not included in the basic trajectory response
|
|
318
|
+
)
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
def _convert_pb_adjudicated_trajectory_to_sdk(
|
|
322
|
+
pb_response: harness_pb2.GetTrajectoryResponse,
|
|
323
|
+
) -> AdjudicatedTrajectory:
|
|
324
|
+
"""Convert protobuf GetTrajectoryResponse to SDK AdjudicatedTrajectory."""
|
|
325
|
+
# Convert the trajectory
|
|
326
|
+
pb_trajectory = (
|
|
327
|
+
pb_response.trajectory if pb_response.HasField("trajectory") else None
|
|
328
|
+
)
|
|
329
|
+
if pb_trajectory is None:
|
|
330
|
+
raise ValueError("GetTrajectoryResponse must have a trajectory field")
|
|
331
|
+
|
|
332
|
+
trajectory = _convert_pb_trajectory_to_sdk(pb_trajectory)
|
|
333
|
+
|
|
334
|
+
# Convert adjudicated steps
|
|
335
|
+
adjudicated_steps = [
|
|
336
|
+
_convert_pb_adjudicated_step_to_sdk(pb_step) for pb_step in pb_response.steps
|
|
337
|
+
]
|
|
338
|
+
|
|
339
|
+
# Exclude steps from trajectory.model_dump() since AdjudicatedTrajectory uses AdjudicatedStep instead
|
|
340
|
+
trajectory_dict = trajectory.model_dump(exclude={"steps"})
|
|
341
|
+
return AdjudicatedTrajectory(**trajectory_dict, steps=adjudicated_steps)
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
def _convert_pb_adjudication_record_to_sdk(
|
|
345
|
+
pb_record: harness_pb2.AdjudicationRecord,
|
|
346
|
+
) -> AdjudicationRecord:
|
|
347
|
+
"""Convert protobuf AdjudicationRecord to SDK AdjudicationRecord."""
|
|
348
|
+
adjudication = _convert_pb_adjudication_to_sdk(pb_record.adjudication)
|
|
349
|
+
return AdjudicationRecord(
|
|
350
|
+
agent_id=pb_record.agent_id,
|
|
351
|
+
trajectory_id=pb_record.trajectory_id,
|
|
352
|
+
step_id=pb_record.step_id,
|
|
353
|
+
adjudication=adjudication,
|
|
354
|
+
)
|