Skip to content

Commit c050ae5

Browse files
Reuse job request helpers across agent utilities
Co-authored-by: Shri Sukhani <shrisukhani@users.noreply.github.com>
1 parent 42af140 commit c050ae5

10 files changed

+301
-267
lines changed
Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from typing import Any, Dict, Type, TypeVar
22

3-
from .response_utils import parse_response_model
3+
from .job_request_utils import start_job, start_job_async
44

55
T = TypeVar("T")
66

@@ -13,12 +13,10 @@ def start_agent_task(
1313
model: Type[T],
1414
operation_name: str,
1515
) -> T:
16-
response = client.transport.post(
17-
client._build_url(route_prefix),
18-
data=payload,
19-
)
20-
return parse_response_model(
21-
response.data,
16+
return start_job(
17+
client=client,
18+
route_prefix=route_prefix,
19+
payload=payload,
2220
model=model,
2321
operation_name=operation_name,
2422
)
@@ -32,12 +30,10 @@ async def start_agent_task_async(
3230
model: Type[T],
3331
operation_name: str,
3432
) -> T:
35-
response = await client.transport.post(
36-
client._build_url(route_prefix),
37-
data=payload,
38-
)
39-
return parse_response_model(
40-
response.data,
33+
return await start_job_async(
34+
client=client,
35+
route_prefix=route_prefix,
36+
payload=payload,
4137
model=model,
4238
operation_name=operation_name,
4339
)

hyperbrowser/client/managers/agent_stop_utils.py

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22

33
from hyperbrowser.models import BasicResponse
44

5-
from .job_route_builders import build_job_action_route
6-
from .response_utils import parse_response_model
5+
from .job_request_utils import put_job_action, put_job_action_async
76

87

98
def stop_agent_task(
@@ -13,13 +12,11 @@ def stop_agent_task(
1312
job_id: str,
1413
operation_name: str,
1514
) -> BasicResponse:
16-
response = client.transport.put(
17-
client._build_url(
18-
build_job_action_route(route_prefix, job_id, "/stop"),
19-
),
20-
)
21-
return parse_response_model(
22-
response.data,
15+
return put_job_action(
16+
client=client,
17+
route_prefix=route_prefix,
18+
job_id=job_id,
19+
action_suffix="/stop",
2320
model=BasicResponse,
2421
operation_name=operation_name,
2522
)
@@ -32,13 +29,11 @@ async def stop_agent_task_async(
3229
job_id: str,
3330
operation_name: str,
3431
) -> BasicResponse:
35-
response = await client.transport.put(
36-
client._build_url(
37-
build_job_action_route(route_prefix, job_id, "/stop"),
38-
),
39-
)
40-
return parse_response_model(
41-
response.data,
32+
return await put_job_action_async(
33+
client=client,
34+
route_prefix=route_prefix,
35+
job_id=job_id,
36+
action_suffix="/stop",
4237
model=BasicResponse,
4338
operation_name=operation_name,
4439
)

hyperbrowser/client/managers/agent_task_read_utils.py

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
from typing import Any, Type, TypeVar
22

3-
from .job_route_builders import build_job_route, build_job_status_route
4-
from .response_utils import parse_response_model
3+
from .job_request_utils import (
4+
get_job,
5+
get_job_async,
6+
get_job_status,
7+
get_job_status_async,
8+
)
59

610
T = TypeVar("T")
711

@@ -14,11 +18,11 @@ def get_agent_task(
1418
model: Type[T],
1519
operation_name: str,
1620
) -> T:
17-
response = client.transport.get(
18-
client._build_url(build_job_route(route_prefix, job_id)),
19-
)
20-
return parse_response_model(
21-
response.data,
21+
return get_job(
22+
client=client,
23+
route_prefix=route_prefix,
24+
job_id=job_id,
25+
params=None,
2226
model=model,
2327
operation_name=operation_name,
2428
)
@@ -32,11 +36,10 @@ def get_agent_task_status(
3236
model: Type[T],
3337
operation_name: str,
3438
) -> T:
35-
response = client.transport.get(
36-
client._build_url(build_job_status_route(route_prefix, job_id)),
37-
)
38-
return parse_response_model(
39-
response.data,
39+
return get_job_status(
40+
client=client,
41+
route_prefix=route_prefix,
42+
job_id=job_id,
4043
model=model,
4144
operation_name=operation_name,
4245
)
@@ -50,11 +53,11 @@ async def get_agent_task_async(
5053
model: Type[T],
5154
operation_name: str,
5255
) -> T:
53-
response = await client.transport.get(
54-
client._build_url(build_job_route(route_prefix, job_id)),
55-
)
56-
return parse_response_model(
57-
response.data,
56+
return await get_job_async(
57+
client=client,
58+
route_prefix=route_prefix,
59+
job_id=job_id,
60+
params=None,
5861
model=model,
5962
operation_name=operation_name,
6063
)
@@ -68,11 +71,10 @@ async def get_agent_task_status_async(
6871
model: Type[T],
6972
operation_name: str,
7073
) -> T:
71-
response = await client.transport.get(
72-
client._build_url(build_job_status_route(route_prefix, job_id)),
73-
)
74-
return parse_response_model(
75-
response.data,
74+
return await get_job_status_async(
75+
client=client,
76+
route_prefix=route_prefix,
77+
job_id=job_id,
7678
model=model,
7779
operation_name=operation_name,
7880
)

hyperbrowser/client/managers/job_request_utils.py

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
from typing import Any, Dict, Optional, Type, TypeVar
22

3-
from .job_route_builders import build_job_route, build_job_status_route
3+
from .job_route_builders import (
4+
build_job_action_route,
5+
build_job_route,
6+
build_job_status_route,
7+
)
48
from .response_utils import parse_response_model
59

610
T = TypeVar("T")
@@ -118,3 +122,41 @@ async def get_job_async(
118122
model=model,
119123
operation_name=operation_name,
120124
)
125+
126+
127+
def put_job_action(
128+
*,
129+
client: Any,
130+
route_prefix: str,
131+
job_id: str,
132+
action_suffix: str,
133+
model: Type[T],
134+
operation_name: str,
135+
) -> T:
136+
response = client.transport.put(
137+
client._build_url(build_job_action_route(route_prefix, job_id, action_suffix)),
138+
)
139+
return parse_response_model(
140+
response.data,
141+
model=model,
142+
operation_name=operation_name,
143+
)
144+
145+
146+
async def put_job_action_async(
147+
*,
148+
client: Any,
149+
route_prefix: str,
150+
job_id: str,
151+
action_suffix: str,
152+
model: Type[T],
153+
operation_name: str,
154+
) -> T:
155+
response = await client.transport.put(
156+
client._build_url(build_job_action_route(route_prefix, job_id, action_suffix)),
157+
)
158+
return parse_response_model(
159+
response.data,
160+
model=model,
161+
operation_name=operation_name,
162+
)

tests/test_agent_route_builder_usage.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,21 @@
55
pytestmark = pytest.mark.architecture
66

77

8-
def test_agent_task_read_helpers_use_shared_job_route_builders():
8+
def test_agent_task_read_helpers_reuse_job_request_helpers():
99
module_text = Path(
1010
"hyperbrowser/client/managers/agent_task_read_utils.py"
1111
).read_text(encoding="utf-8")
12-
assert "job_route_builders import build_job_route, build_job_status_route" in module_text
13-
assert "build_job_route(route_prefix, job_id)" in module_text
14-
assert "build_job_status_route(route_prefix, job_id)" in module_text
15-
assert 'f"{route_prefix}/{job_id}"' not in module_text
16-
assert 'f"{route_prefix}/{job_id}/status"' not in module_text
12+
assert "job_request_utils import" in module_text
13+
assert "get_job(" in module_text
14+
assert "get_job_status(" in module_text
15+
assert "get_job_async(" in module_text
16+
assert "get_job_status_async(" in module_text
1717

1818

19-
def test_agent_stop_helpers_use_shared_job_route_builders():
19+
def test_agent_stop_helpers_reuse_job_request_helpers():
2020
module_text = Path("hyperbrowser/client/managers/agent_stop_utils.py").read_text(
2121
encoding="utf-8"
2222
)
23-
assert "job_route_builders import build_job_action_route" in module_text
24-
assert 'build_job_action_route(route_prefix, job_id, "/stop")' in module_text
25-
assert 'f"{route_prefix}/{job_id}/stop"' not in module_text
23+
assert "job_request_utils import put_job_action, put_job_action_async" in module_text
24+
assert "put_job_action(" in module_text
25+
assert "put_job_action_async(" in module_text

tests/test_agent_start_utils.py

Lines changed: 20 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,88 +1,57 @@
11
import asyncio
2-
from types import SimpleNamespace
32

43
import hyperbrowser.client.managers.agent_start_utils as agent_start_utils
54

65

7-
def test_start_agent_task_builds_start_url_and_parses_response():
6+
def test_start_agent_task_delegates_to_start_job():
87
captured = {}
98

10-
class _SyncTransport:
11-
def post(self, url, data):
12-
captured["url"] = url
13-
captured["data"] = data
14-
return SimpleNamespace(data={"id": "job-1"})
15-
16-
class _Client:
17-
transport = _SyncTransport()
18-
19-
@staticmethod
20-
def _build_url(path: str) -> str:
21-
return f"https://api.example.test{path}"
22-
23-
def _fake_parse_response_model(data, **kwargs):
24-
captured["parse_data"] = data
25-
captured["parse_kwargs"] = kwargs
9+
def _fake_start_job(**kwargs):
10+
captured.update(kwargs)
2611
return {"parsed": True}
2712

28-
original_parse = agent_start_utils.parse_response_model
29-
agent_start_utils.parse_response_model = _fake_parse_response_model
13+
original_start_job = agent_start_utils.start_job
14+
agent_start_utils.start_job = _fake_start_job
3015
try:
3116
result = agent_start_utils.start_agent_task(
32-
client=_Client(),
17+
client=object(),
3318
route_prefix="/task/cua",
3419
payload={"task": "open docs"},
3520
model=object,
3621
operation_name="cua start",
3722
)
3823
finally:
39-
agent_start_utils.parse_response_model = original_parse
24+
agent_start_utils.start_job = original_start_job
4025

4126
assert result == {"parsed": True}
42-
assert captured["url"] == "https://api.example.test/task/cua"
43-
assert captured["data"] == {"task": "open docs"}
44-
assert captured["parse_data"] == {"id": "job-1"}
45-
assert captured["parse_kwargs"]["operation_name"] == "cua start"
27+
assert captured["route_prefix"] == "/task/cua"
28+
assert captured["payload"] == {"task": "open docs"}
29+
assert captured["operation_name"] == "cua start"
4630

4731

48-
def test_start_agent_task_async_builds_start_url_and_parses_response():
32+
def test_start_agent_task_async_delegates_to_start_job_async():
4933
captured = {}
5034

51-
class _AsyncTransport:
52-
async def post(self, url, data):
53-
captured["url"] = url
54-
captured["data"] = data
55-
return SimpleNamespace(data={"id": "job-2"})
56-
57-
class _Client:
58-
transport = _AsyncTransport()
59-
60-
@staticmethod
61-
def _build_url(path: str) -> str:
62-
return f"https://api.example.test{path}"
63-
64-
def _fake_parse_response_model(data, **kwargs):
65-
captured["parse_data"] = data
66-
captured["parse_kwargs"] = kwargs
35+
async def _fake_start_job_async(**kwargs):
36+
captured.update(kwargs)
6737
return {"parsed": True}
6838

69-
original_parse = agent_start_utils.parse_response_model
70-
agent_start_utils.parse_response_model = _fake_parse_response_model
39+
original_start_job_async = agent_start_utils.start_job_async
40+
agent_start_utils.start_job_async = _fake_start_job_async
7141
try:
7242
result = asyncio.run(
7343
agent_start_utils.start_agent_task_async(
74-
client=_Client(),
44+
client=object(),
7545
route_prefix="/task/browser-use",
7646
payload={"task": "browse"},
7747
model=object,
7848
operation_name="browser-use start",
7949
)
8050
)
8151
finally:
82-
agent_start_utils.parse_response_model = original_parse
52+
agent_start_utils.start_job_async = original_start_job_async
8353

8454
assert result == {"parsed": True}
85-
assert captured["url"] == "https://api.example.test/task/browser-use"
86-
assert captured["data"] == {"task": "browse"}
87-
assert captured["parse_data"] == {"id": "job-2"}
88-
assert captured["parse_kwargs"]["operation_name"] == "browser-use start"
55+
assert captured["route_prefix"] == "/task/browser-use"
56+
assert captured["payload"] == {"task": "browse"}
57+
assert captured["operation_name"] == "browser-use start"

0 commit comments

Comments
 (0)