Skip to content

Commit 5a08993

Browse files
authored
Merge pull request #3 from browser-use/release-please--branches--main--changes--next
release: 0.2.0
2 parents 76f7597 + 461d190 commit 5a08993

File tree

8 files changed

+79
-51
lines changed

8 files changed

+79
-51
lines changed

.release-please-manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
".": "0.1.0"
2+
".": "0.2.0"
33
}

.stats.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
configured_endpoints: 26
2-
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browser-use%2Fbrowser-use-3a9488448292a0736b08b2d6427e702eaf7106d86345ca2e65b64bed4398b036.yml
3-
openapi_spec_hash: 5ff2781dcc11a0c9aa353f5cb14bcc16
4-
config_hash: 9d52be5177b2ede4cb0633c04f4cc4ef
2+
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browser-use%2Fbrowser-use-ce018db4d6891d645cfb220c86d17ac1d431e1ba2f604e8015876b17a5a11149.yml
3+
openapi_spec_hash: e9a00924682ab214ca5d8b6b5c84430e
4+
config_hash: dd3e22b635fa0eb9a7c741a8aaca2a7f

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
# Changelog
22

3+
## 0.2.0 (2025-08-19)
4+
5+
Full Changelog: [v0.1.0...v0.2.0](https://github.com/browser-use/browser-use-python/compare/v0.1.0...v0.2.0)
6+
7+
### Features
8+
9+
* **api:** manual updates ([6266282](https://github.com/browser-use/browser-use-python/commit/6266282a615344fdab0737d29adc9124a3bf8b8d))
10+
* **api:** manual updates ([2d9ba52](https://github.com/browser-use/browser-use-python/commit/2d9ba52b23e53c581360afc655fa8d665a106814))
11+
* Improve Docs ([6e79b7c](https://github.com/browser-use/browser-use-python/commit/6e79b7c5cfc7cf54f1474521025fa713f200bc3b))
12+
313
## 0.1.0 (2025-08-18)
414

515
Full Changelog: [v0.0.2...v0.1.0](https://github.com/browser-use/browser-use-python/compare/v0.0.2...v0.1.0)

README.md

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,10 @@ client = BrowserUse(
3232
api_key=os.environ.get("BROWSER_USE_API_KEY"), # This is the default and can be omitted
3333
)
3434

35-
me = client.users.me.retrieve()
36-
print(me.additional_credits_balance_usd)
35+
task = client.tasks.create(
36+
task="Search for the top 10 Hacker News posts and return the title and url.",
37+
)
38+
print(task.id)
3739
```
3840

3941
While you can provide an `api_key` keyword argument,
@@ -56,8 +58,10 @@ client = AsyncBrowserUse(
5658

5759

5860
async def main() -> None:
59-
me = await client.users.me.retrieve()
60-
print(me.additional_credits_balance_usd)
61+
task = await client.tasks.create(
62+
task="Search for the top 10 Hacker News posts and return the title and url.",
63+
)
64+
print(task.id)
6165

6266

6367
asyncio.run(main())
@@ -89,8 +93,10 @@ async def main() -> None:
8993
api_key="My API Key",
9094
http_client=DefaultAioHttpClient(),
9195
) as client:
92-
me = await client.users.me.retrieve()
93-
print(me.additional_credits_balance_usd)
96+
task = await client.tasks.create(
97+
task="Search for the top 10 Hacker News posts and return the title and url.",
98+
)
99+
print(task.id)
94100

95101

96102
asyncio.run(main())
@@ -137,7 +143,9 @@ from browser_use_sdk import BrowserUse
137143
client = BrowserUse()
138144

139145
try:
140-
client.users.me.retrieve()
146+
client.tasks.create(
147+
task="Search for the top 10 Hacker News posts and return the title and url.",
148+
)
141149
except browser_use_sdk.APIConnectionError as e:
142150
print("The server could not be reached")
143151
print(e.__cause__) # an underlying Exception, likely raised within httpx.
@@ -180,7 +188,9 @@ client = BrowserUse(
180188
)
181189

182190
# Or, configure per-request:
183-
client.with_options(max_retries=5).users.me.retrieve()
191+
client.with_options(max_retries=5).tasks.create(
192+
task="Search for the top 10 Hacker News posts and return the title and url.",
193+
)
184194
```
185195

186196
### Timeouts
@@ -203,7 +213,9 @@ client = BrowserUse(
203213
)
204214

205215
# Override per-request:
206-
client.with_options(timeout=5.0).users.me.retrieve()
216+
client.with_options(timeout=5.0).tasks.create(
217+
task="Search for the top 10 Hacker News posts and return the title and url.",
218+
)
207219
```
208220

209221
On timeout, an `APITimeoutError` is thrown.
@@ -244,11 +256,13 @@ The "raw" Response object can be accessed by prefixing `.with_raw_response.` to
244256
from browser_use_sdk import BrowserUse
245257

246258
client = BrowserUse()
247-
response = client.users.me.with_raw_response.retrieve()
259+
response = client.tasks.with_raw_response.create(
260+
task="Search for the top 10 Hacker News posts and return the title and url.",
261+
)
248262
print(response.headers.get('X-My-Header'))
249263

250-
me = response.parse() # get the object that `users.me.retrieve()` would have returned
251-
print(me.additional_credits_balance_usd)
264+
task = response.parse() # get the object that `tasks.create()` would have returned
265+
print(task.id)
252266
```
253267

254268
These methods return an [`APIResponse`](https://github.com/browser-use/browser-use-python/tree/main/src/browser_use_sdk/_response.py) object.
@@ -262,7 +276,9 @@ The above interface eagerly reads the full response body when you make the reque
262276
To stream the response body, use `.with_streaming_response` instead, which requires a context manager and only reads the response body once you call `.read()`, `.text()`, `.json()`, `.iter_bytes()`, `.iter_text()`, `.iter_lines()` or `.parse()`. In the async client, these are async methods.
263277

264278
```python
265-
with client.users.me.with_streaming_response.retrieve() as response:
279+
with client.tasks.with_streaming_response.create(
280+
task="Search for the top 10 Hacker News posts and return the title and url.",
281+
) as response:
266282
print(response.headers.get("X-My-Header"))
267283

268284
for line in response.iter_lines():

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "browser-use-sdk"
3-
version = "0.1.0"
3+
version = "0.2.0"
44
description = "The official Python library for the browser-use API"
55
dynamic = ["readme"]
66
license = "Apache-2.0"

src/browser_use_sdk/_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
22

33
__title__ = "browser_use_sdk"
4-
__version__ = "0.1.0" # x-release-please-version
4+
__version__ = "0.2.0" # x-release-please-version

src/browser_use_sdk/resources/tasks.py

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,12 @@ def create(
6969
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
7070
) -> TaskCreateResponse:
7171
"""
72-
Create and start a new AI agent task.
72+
Create and start a new Browser Use Agent task.
7373
7474
This is the main endpoint for running AI agents. You can either:
7575
76-
1. Start a new session with a new task
77-
2. Add a follow-up task to an existing session
76+
1. Start a new session with a new task.
77+
2. Add a follow-up task to an existing session.
7878
7979
When starting a new session:
8080
@@ -95,9 +95,8 @@ def create(
9595
- Browser profiles: Control browser settings and environment (only used for new
9696
sessions)
9797
- File uploads: Include documents for the agent to work with
98-
- Structured output: Define the format you want results in
99-
- Task metadata: Add custom data for tracking and organization (useful when
100-
using webhooks)
98+
- Structured output: Define the format of the task result
99+
- Task metadata: Add custom data for tracking and organization
101100
102101
Args:
103102
@@ -564,12 +563,12 @@ async def create(
564563
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
565564
) -> TaskCreateResponse:
566565
"""
567-
Create and start a new AI agent task.
566+
Create and start a new Browser Use Agent task.
568567
569568
This is the main endpoint for running AI agents. You can either:
570569
571-
1. Start a new session with a new task
572-
2. Add a follow-up task to an existing session
570+
1. Start a new session with a new task.
571+
2. Add a follow-up task to an existing session.
573572
574573
When starting a new session:
575574
@@ -590,9 +589,8 @@ async def create(
590589
- Browser profiles: Control browser settings and environment (only used for new
591590
sessions)
592591
- File uploads: Include documents for the agent to work with
593-
- Structured output: Define the format you want results in
594-
- Task metadata: Add custom data for tracking and organization (useful when
595-
using webhooks)
592+
- Structured output: Define the format of the task result
593+
- Task metadata: Add custom data for tracking and organization
596594
597595
Args:
598596

tests/test_client.py

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -722,20 +722,20 @@ def test_parse_retry_after_header(self, remaining_retries: int, retry_after: str
722722
@mock.patch("browser_use_sdk._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout)
723723
@pytest.mark.respx(base_url=base_url)
724724
def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter, client: BrowserUse) -> None:
725-
respx_mock.get("/users/me").mock(side_effect=httpx.TimeoutException("Test timeout error"))
725+
respx_mock.post("/tasks").mock(side_effect=httpx.TimeoutException("Test timeout error"))
726726

727727
with pytest.raises(APITimeoutError):
728-
client.users.me.with_streaming_response.retrieve().__enter__()
728+
client.tasks.with_streaming_response.create(task="x").__enter__()
729729

730730
assert _get_open_connections(self.client) == 0
731731

732732
@mock.patch("browser_use_sdk._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout)
733733
@pytest.mark.respx(base_url=base_url)
734734
def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter, client: BrowserUse) -> None:
735-
respx_mock.get("/users/me").mock(return_value=httpx.Response(500))
735+
respx_mock.post("/tasks").mock(return_value=httpx.Response(500))
736736

737737
with pytest.raises(APIStatusError):
738-
client.users.me.with_streaming_response.retrieve().__enter__()
738+
client.tasks.with_streaming_response.create(task="x").__enter__()
739739
assert _get_open_connections(self.client) == 0
740740

741741
@pytest.mark.parametrize("failures_before_success", [0, 2, 4])
@@ -762,9 +762,9 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
762762
return httpx.Response(500)
763763
return httpx.Response(200)
764764

765-
respx_mock.get("/users/me").mock(side_effect=retry_handler)
765+
respx_mock.post("/tasks").mock(side_effect=retry_handler)
766766

767-
response = client.users.me.with_raw_response.retrieve()
767+
response = client.tasks.with_raw_response.create(task="x")
768768

769769
assert response.retries_taken == failures_before_success
770770
assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success
@@ -786,9 +786,9 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
786786
return httpx.Response(500)
787787
return httpx.Response(200)
788788

789-
respx_mock.get("/users/me").mock(side_effect=retry_handler)
789+
respx_mock.post("/tasks").mock(side_effect=retry_handler)
790790

791-
response = client.users.me.with_raw_response.retrieve(extra_headers={"x-stainless-retry-count": Omit()})
791+
response = client.tasks.with_raw_response.create(task="x", extra_headers={"x-stainless-retry-count": Omit()})
792792

793793
assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0
794794

@@ -809,9 +809,9 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
809809
return httpx.Response(500)
810810
return httpx.Response(200)
811811

812-
respx_mock.get("/users/me").mock(side_effect=retry_handler)
812+
respx_mock.post("/tasks").mock(side_effect=retry_handler)
813813

814-
response = client.users.me.with_raw_response.retrieve(extra_headers={"x-stainless-retry-count": "42"})
814+
response = client.tasks.with_raw_response.create(task="x", extra_headers={"x-stainless-retry-count": "42"})
815815

816816
assert response.http_request.headers.get("x-stainless-retry-count") == "42"
817817

@@ -1539,10 +1539,10 @@ async def test_parse_retry_after_header(self, remaining_retries: int, retry_afte
15391539
async def test_retrying_timeout_errors_doesnt_leak(
15401540
self, respx_mock: MockRouter, async_client: AsyncBrowserUse
15411541
) -> None:
1542-
respx_mock.get("/users/me").mock(side_effect=httpx.TimeoutException("Test timeout error"))
1542+
respx_mock.post("/tasks").mock(side_effect=httpx.TimeoutException("Test timeout error"))
15431543

15441544
with pytest.raises(APITimeoutError):
1545-
await async_client.users.me.with_streaming_response.retrieve().__aenter__()
1545+
await async_client.tasks.with_streaming_response.create(task="x").__aenter__()
15461546

15471547
assert _get_open_connections(self.client) == 0
15481548

@@ -1551,10 +1551,10 @@ async def test_retrying_timeout_errors_doesnt_leak(
15511551
async def test_retrying_status_errors_doesnt_leak(
15521552
self, respx_mock: MockRouter, async_client: AsyncBrowserUse
15531553
) -> None:
1554-
respx_mock.get("/users/me").mock(return_value=httpx.Response(500))
1554+
respx_mock.post("/tasks").mock(return_value=httpx.Response(500))
15551555

15561556
with pytest.raises(APIStatusError):
1557-
await async_client.users.me.with_streaming_response.retrieve().__aenter__()
1557+
await async_client.tasks.with_streaming_response.create(task="x").__aenter__()
15581558
assert _get_open_connections(self.client) == 0
15591559

15601560
@pytest.mark.parametrize("failures_before_success", [0, 2, 4])
@@ -1582,9 +1582,9 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
15821582
return httpx.Response(500)
15831583
return httpx.Response(200)
15841584

1585-
respx_mock.get("/users/me").mock(side_effect=retry_handler)
1585+
respx_mock.post("/tasks").mock(side_effect=retry_handler)
15861586

1587-
response = await client.users.me.with_raw_response.retrieve()
1587+
response = await client.tasks.with_raw_response.create(task="x")
15881588

15891589
assert response.retries_taken == failures_before_success
15901590
assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success
@@ -1607,9 +1607,11 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
16071607
return httpx.Response(500)
16081608
return httpx.Response(200)
16091609

1610-
respx_mock.get("/users/me").mock(side_effect=retry_handler)
1610+
respx_mock.post("/tasks").mock(side_effect=retry_handler)
16111611

1612-
response = await client.users.me.with_raw_response.retrieve(extra_headers={"x-stainless-retry-count": Omit()})
1612+
response = await client.tasks.with_raw_response.create(
1613+
task="x", extra_headers={"x-stainless-retry-count": Omit()}
1614+
)
16131615

16141616
assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0
16151617

@@ -1631,9 +1633,11 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
16311633
return httpx.Response(500)
16321634
return httpx.Response(200)
16331635

1634-
respx_mock.get("/users/me").mock(side_effect=retry_handler)
1636+
respx_mock.post("/tasks").mock(side_effect=retry_handler)
16351637

1636-
response = await client.users.me.with_raw_response.retrieve(extra_headers={"x-stainless-retry-count": "42"})
1638+
response = await client.tasks.with_raw_response.create(
1639+
task="x", extra_headers={"x-stainless-retry-count": "42"}
1640+
)
16371641

16381642
assert response.http_request.headers.get("x-stainless-retry-count") == "42"
16391643

0 commit comments

Comments
 (0)