Skip to content

Commit b0120da

Browse files
Fix GrokComputerUseStepResponse xAI-style step field types
Align created_at, completed_at, and error with CuaStepResponse so completed Grok task payloads parse without Pydantic validation errors. Reuse CUA step helper models for structured error, incomplete_details, and reasoning fields. Co-authored-by: Shri Sukhani <shrisukhani@users.noreply.github.com>
1 parent 887e54a commit b0120da

2 files changed

Lines changed: 47 additions & 5 deletions

File tree

‎hyperbrowser/models/agents/grok_computer_use.py‎

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from pydantic import BaseModel, ConfigDict, Field
44

5+
from .cua import CuaStepIncompleteDetails, CuaStepReasoning, CuaStepResponseError
56
from ..session import CreateSessionParams
67
from ..consts import GrokComputerUseLlm, GrokReasoningEffort
78

@@ -90,18 +91,22 @@ class GrokComputerUseStepResponse(BaseModel):
9091
populate_by_alias=True,
9192
)
9293

93-
created_at: Optional[str] = Field(default=None, serialization_alias="created_at")
94-
completed_at: Optional[str] = Field(
94+
created_at: Optional[int] = Field(default=None, serialization_alias="created_at")
95+
completed_at: Optional[int] = Field(
9596
default=None, serialization_alias="completed_at"
9697
)
9798
output_text: Optional[str] = Field(default=None, serialization_alias="output_text")
98-
error: Optional[str] = Field(default=None, serialization_alias="error")
99-
incomplete_details: Optional[Any] = Field(
99+
error: Optional[CuaStepResponseError] = Field(
100+
default=None, serialization_alias="error"
101+
)
102+
incomplete_details: Optional[CuaStepIncompleteDetails] = Field(
100103
default=None, serialization_alias="incomplete_details"
101104
)
102105
model: Optional[str] = Field(default=None, serialization_alias="model")
103106
output: Optional[list[Any]] = Field(default=None, serialization_alias="output")
104-
reasoning: Optional[Any] = Field(default=None, serialization_alias="reasoning")
107+
reasoning: Optional[CuaStepReasoning] = Field(
108+
default=None, serialization_alias="reasoning"
109+
)
105110
status: Optional[str] = Field(default=None, serialization_alias="status")
106111

107112

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
from hyperbrowser.models.agents.grok_computer_use import GrokComputerUseTaskResponse
2+
3+
4+
def test_grok_computer_use_task_response_parses_xai_style_step_payload() -> None:
5+
payload = {
6+
"jobId": "job-123",
7+
"status": "completed",
8+
"data": {
9+
"steps": [
10+
{
11+
"created_at": 1710000000,
12+
"completed_at": 1710000001,
13+
"output_text": "done",
14+
"error": {"code": "ERR", "message": "something failed"},
15+
"incomplete_details": {"reason": "timeout"},
16+
"model": "grok-4.5",
17+
"output": [],
18+
"reasoning": {"effort": "high"},
19+
"status": "completed",
20+
}
21+
],
22+
"finalResult": "result",
23+
},
24+
}
25+
26+
result = GrokComputerUseTaskResponse(**payload)
27+
28+
step = result.data.steps[0]
29+
assert step.created_at == 1710000000
30+
assert step.completed_at == 1710000001
31+
assert step.error is not None
32+
assert step.error.code == "ERR"
33+
assert step.error.message == "something failed"
34+
assert step.incomplete_details is not None
35+
assert step.incomplete_details.reason == "timeout"
36+
assert step.reasoning is not None
37+
assert step.reasoning.effort == "high"

0 commit comments

Comments
 (0)