diff --git a/.release-please-manifest.json b/.release-please-manifest.json index c7159c1..3d2ac0b 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.0.2" + ".": "0.1.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 27116f1..8a02f60 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 22 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browser-use%2Fbrowser-use-86040fd18419e7b4e0947660d9c0ff1abe21550528d2d2a549736cd16f85a92d.yml -openapi_spec_hash: 7c5de9d0f633db35fd9e250fcc834d1f -config_hash: 771e55285d36ab0c796ac0f29840fa8f +configured_endpoints: 26 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browser-use%2Fbrowser-use-3a9488448292a0736b08b2d6427e702eaf7106d86345ca2e65b64bed4398b036.yml +openapi_spec_hash: 5ff2781dcc11a0c9aa353f5cb14bcc16 +config_hash: 9d52be5177b2ede4cb0633c04f4cc4ef diff --git a/CHANGELOG.md b/CHANGELOG.md index 2cd7d38..91a872a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,24 @@ # Changelog +## 0.1.0 (2025-08-18) + +Full Changelog: [v0.0.2...v0.1.0](https://github.com/browser-use/browser-use-python/compare/v0.0.2...v0.1.0) + +### Features + +* Add start_url ([2ede0a9](https://github.com/browser-use/browser-use-python/commit/2ede0a9089bfbba1eca207508a52ee36b4ef18ac)) +* Align Task Filtering by Status with `status` Field ([29b4590](https://github.com/browser-use/browser-use-python/commit/29b4590c69f13fbf7f855888862ef77a9e704172)) +* **api:** api update ([5867532](https://github.com/browser-use/browser-use-python/commit/58675327b6a0e7ba41f312e4887062a9b6dc2852)) +* **api:** manual updates ([78727c0](https://github.com/browser-use/browser-use-python/commit/78727c02cefa53fd0dd877e137b7b6f92e14fce8)) +* **api:** update via SDK Studio ([b283386](https://github.com/browser-use/browser-use-python/commit/b283386b805435a87114e807f8919185cb6a5b7b)) +* Fix Stainless GitHub Action ([5dcf360](https://github.com/browser-use/browser-use-python/commit/5dcf360ccfe40f45962ecaa64b8a5aacf55778d4)) +* Update param and response views ([44b4c5d](https://github.com/browser-use/browser-use-python/commit/44b4c5d7ed416f9f5c37afb3287cdaa6f22a30cd)) + + +### Chores + +* **internal:** codegen related update ([151d56b](https://github.com/browser-use/browser-use-python/commit/151d56ba67c2d09970ff415472c0a1d259716bbc)) + ## 0.0.2 (2025-08-09) Full Changelog: [v0.0.1...v0.0.2](https://github.com/browser-use/browser-use-python/compare/v0.0.1...v0.0.2) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 673519a..5338abc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -36,7 +36,7 @@ $ pip install -r requirements-dev.lock Most of the SDK is generated code. Modifications to code will be persisted between generations, but may result in merge conflicts between manual patches and changes from the generator. The generator will never -modify the contents of the `src/browser_use/lib/` and `examples/` directories. +modify the contents of the `src/browser_use_sdk/lib/` and `examples/` directories. ## Adding and running examples diff --git a/README.md b/README.md index 2d5cae8..6a1320b 100644 --- a/README.md +++ b/README.md @@ -26,14 +26,14 @@ The full API of this library can be found in [api.md](api.md). ```python import os -from browser_use import BrowserUse +from browser_use_sdk import BrowserUse client = BrowserUse( api_key=os.environ.get("BROWSER_USE_API_KEY"), # This is the default and can be omitted ) -tasks = client.tasks.list() -print(tasks.items) +me = client.users.me.retrieve() +print(me.additional_credits_balance_usd) ``` While you can provide an `api_key` keyword argument, @@ -48,7 +48,7 @@ Simply import `AsyncBrowserUse` instead of `BrowserUse` and use `await` with eac ```python import os import asyncio -from browser_use import AsyncBrowserUse +from browser_use_sdk import AsyncBrowserUse client = AsyncBrowserUse( api_key=os.environ.get("BROWSER_USE_API_KEY"), # This is the default and can be omitted @@ -56,8 +56,8 @@ client = AsyncBrowserUse( async def main() -> None: - tasks = await client.tasks.list() - print(tasks.items) + me = await client.users.me.retrieve() + print(me.additional_credits_balance_usd) asyncio.run(main()) @@ -80,8 +80,8 @@ Then you can enable it by instantiating the client with `http_client=DefaultAioH ```python import asyncio -from browser_use import DefaultAioHttpClient -from browser_use import AsyncBrowserUse +from browser_use_sdk import DefaultAioHttpClient +from browser_use_sdk import AsyncBrowserUse async def main() -> None: @@ -89,8 +89,8 @@ async def main() -> None: api_key="My API Key", http_client=DefaultAioHttpClient(), ) as client: - tasks = await client.tasks.list() - print(tasks.items) + me = await client.users.me.retrieve() + print(me.additional_credits_balance_usd) asyncio.run(main()) @@ -110,40 +110,40 @@ Typed requests and responses provide autocomplete and documentation within your Nested parameters are dictionaries, typed using `TypedDict`, for example: ```python -from browser_use import BrowserUse +from browser_use_sdk import BrowserUse client = BrowserUse() -task_view = client.tasks.create( +task = client.tasks.create( task="x", agent_settings={}, ) -print(task_view.agent_settings) +print(task.agent_settings) ``` ## Handling errors -When the library is unable to connect to the API (for example, due to network connection problems or a timeout), a subclass of `browser_use.APIConnectionError` is raised. +When the library is unable to connect to the API (for example, due to network connection problems or a timeout), a subclass of `browser_use_sdk.APIConnectionError` is raised. When the API returns a non-success status code (that is, 4xx or 5xx -response), a subclass of `browser_use.APIStatusError` is raised, containing `status_code` and `response` properties. +response), a subclass of `browser_use_sdk.APIStatusError` is raised, containing `status_code` and `response` properties. -All errors inherit from `browser_use.APIError`. +All errors inherit from `browser_use_sdk.APIError`. ```python -import browser_use -from browser_use import BrowserUse +import browser_use_sdk +from browser_use_sdk import BrowserUse client = BrowserUse() try: - client.tasks.list() -except browser_use.APIConnectionError as e: + client.users.me.retrieve() +except browser_use_sdk.APIConnectionError as e: print("The server could not be reached") print(e.__cause__) # an underlying Exception, likely raised within httpx. -except browser_use.RateLimitError as e: +except browser_use_sdk.RateLimitError as e: print("A 429 status code was received; we should back off a bit.") -except browser_use.APIStatusError as e: +except browser_use_sdk.APIStatusError as e: print("Another non-200-range status code was received") print(e.status_code) print(e.response) @@ -171,7 +171,7 @@ Connection errors (for example, due to a network connectivity problem), 408 Requ You can use the `max_retries` option to configure or disable retry settings: ```python -from browser_use import BrowserUse +from browser_use_sdk import BrowserUse # Configure the default for all requests: client = BrowserUse( @@ -180,7 +180,7 @@ client = BrowserUse( ) # Or, configure per-request: -client.with_options(max_retries=5).tasks.list() +client.with_options(max_retries=5).users.me.retrieve() ``` ### Timeouts @@ -189,7 +189,7 @@ By default requests time out after 1 minute. You can configure this with a `time which accepts a float or an [`httpx.Timeout`](https://www.python-httpx.org/advanced/timeouts/#fine-tuning-the-configuration) object: ```python -from browser_use import BrowserUse +from browser_use_sdk import BrowserUse # Configure the default for all requests: client = BrowserUse( @@ -203,7 +203,7 @@ client = BrowserUse( ) # Override per-request: -client.with_options(timeout=5.0).tasks.list() +client.with_options(timeout=5.0).users.me.retrieve() ``` On timeout, an `APITimeoutError` is thrown. @@ -241,19 +241,19 @@ if response.my_field is None: The "raw" Response object can be accessed by prefixing `.with_raw_response.` to any HTTP method call, e.g., ```py -from browser_use import BrowserUse +from browser_use_sdk import BrowserUse client = BrowserUse() -response = client.tasks.with_raw_response.list() +response = client.users.me.with_raw_response.retrieve() print(response.headers.get('X-My-Header')) -task = response.parse() # get the object that `tasks.list()` would have returned -print(task.items) +me = response.parse() # get the object that `users.me.retrieve()` would have returned +print(me.additional_credits_balance_usd) ``` -These methods return an [`APIResponse`](https://github.com/browser-use/browser-use-python/tree/main/src/browser_use/_response.py) object. +These methods return an [`APIResponse`](https://github.com/browser-use/browser-use-python/tree/main/src/browser_use_sdk/_response.py) object. -The async client returns an [`AsyncAPIResponse`](https://github.com/browser-use/browser-use-python/tree/main/src/browser_use/_response.py) with the same structure, the only difference being `await`able methods for reading the response content. +The async client returns an [`AsyncAPIResponse`](https://github.com/browser-use/browser-use-python/tree/main/src/browser_use_sdk/_response.py) with the same structure, the only difference being `await`able methods for reading the response content. #### `.with_streaming_response` @@ -262,7 +262,7 @@ The above interface eagerly reads the full response body when you make the reque 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. ```python -with client.tasks.with_streaming_response.list() as response: +with client.users.me.with_streaming_response.retrieve() as response: print(response.headers.get("X-My-Header")) for line in response.iter_lines(): @@ -315,7 +315,7 @@ You can directly override the [httpx client](https://www.python-httpx.org/api/#c ```python import httpx -from browser_use import BrowserUse, DefaultHttpxClient +from browser_use_sdk import BrowserUse, DefaultHttpxClient client = BrowserUse( # Or use the `BROWSER_USE_BASE_URL` env var @@ -338,7 +338,7 @@ client.with_options(http_client=DefaultHttpxClient(...)) By default the library closes underlying HTTP connections whenever the client is [garbage collected](https://docs.python.org/3/reference/datamodel.html#object.__del__). You can manually close the client using the `.close()` method if desired, or with a context manager that closes when exiting. ```py -from browser_use import BrowserUse +from browser_use_sdk import BrowserUse with BrowserUse() as client: # make requests here @@ -366,8 +366,8 @@ If you've upgraded to the latest version but aren't seeing any new features you You can determine the version that is being used at runtime with: ```py -import browser_use -print(browser_use.__version__) +import browser_use_sdk +print(browser_use_sdk.__version__) ``` ## Requirements diff --git a/api.md b/api.md index 44030a3..bddad6f 100644 --- a/api.md +++ b/api.md @@ -1,84 +1,116 @@ +# Users + +## Me + +Types: + +```python +from browser_use_sdk.types.users import MeRetrieveResponse +``` + +Methods: + +- client.users.me.retrieve() -> MeRetrieveResponse + +### Files + +Types: + +```python +from browser_use_sdk.types.users.me import FileCreatePresignedURLResponse +``` + +Methods: + +- client.users.me.files.create_presigned_url(\*\*params) -> FileCreatePresignedURLResponse + # Tasks Types: ```python -from browser_use.types import ( +from browser_use_sdk.types import ( + FileView, LlmModel, + TaskItemView, TaskStatus, + TaskStepView, TaskView, - TaskRetrieveResponse, + TaskCreateResponse, TaskListResponse, - TaskRetrieveLogsResponse, - TaskRetrieveOutputFileResponse, + TaskGetLogsResponse, + TaskGetOutputFileResponse, + TaskGetUserUploadedFileResponse, ) ``` Methods: -- client.tasks.create(\*\*params) -> TaskView -- client.tasks.retrieve(task_id, \*\*params) -> TaskRetrieveResponse -- client.tasks.update(task_id, \*\*params) -> TaskView -- client.tasks.list(\*\*params) -> TaskListResponse -- client.tasks.retrieve_logs(task_id) -> TaskRetrieveLogsResponse -- client.tasks.retrieve_output_file(file_name, \*, task_id) -> TaskRetrieveOutputFileResponse +- client.tasks.create(\*\*params) -> TaskCreateResponse +- client.tasks.retrieve(task_id) -> TaskView +- client.tasks.update(task_id, \*\*params) -> TaskView +- client.tasks.list(\*\*params) -> TaskListResponse +- client.tasks.get_logs(task_id) -> TaskGetLogsResponse +- client.tasks.get_output_file(file_id, \*, task_id) -> TaskGetOutputFileResponse +- client.tasks.get_user_uploaded_file(file_id, \*, task_id) -> TaskGetUserUploadedFileResponse # Sessions Types: ```python -from browser_use.types import SessionStatus, SessionView, SessionListResponse +from browser_use_sdk.types import SessionStatus, SessionView, SessionListResponse ``` Methods: -- client.sessions.retrieve(session_id, \*\*params) -> SessionView -- client.sessions.update(session_id, \*\*params) -> SessionView -- client.sessions.list(\*\*params) -> SessionListResponse +- client.sessions.retrieve(session_id) -> SessionView +- client.sessions.update(session_id, \*\*params) -> SessionView +- client.sessions.list(\*\*params) -> SessionListResponse +- client.sessions.delete(session_id) -> None ## PublicShare Types: ```python -from browser_use.types.sessions import ShareView +from browser_use_sdk.types.sessions import ShareView ``` Methods: -- client.sessions.public_share.create(session_id) -> ShareView -- client.sessions.public_share.retrieve(session_id) -> ShareView -- client.sessions.public_share.delete(session_id) -> object +- client.sessions.public_share.create(session_id) -> ShareView +- client.sessions.public_share.retrieve(session_id) -> ShareView +- client.sessions.public_share.delete(session_id) -> None # BrowserProfiles Types: ```python -from browser_use.types import BrowserProfileView, ProxyCountryCode, BrowserProfileListResponse +from browser_use_sdk.types import BrowserProfileView, ProxyCountryCode, BrowserProfileListResponse ``` Methods: -- client.browser_profiles.create(\*\*params) -> BrowserProfileView -- client.browser_profiles.retrieve(profile_id) -> BrowserProfileView -- client.browser_profiles.update(profile_id, \*\*params) -> BrowserProfileView -- client.browser_profiles.list(\*\*params) -> BrowserProfileListResponse -- client.browser_profiles.delete(profile_id) -> object +- client.browser_profiles.create(\*\*params) -> BrowserProfileView +- client.browser_profiles.retrieve(profile_id) -> BrowserProfileView +- client.browser_profiles.update(profile_id, \*\*params) -> BrowserProfileView +- client.browser_profiles.list(\*\*params) -> BrowserProfileListResponse +- client.browser_profiles.delete(profile_id) -> None # AgentProfiles Types: ```python -from browser_use.types import AgentProfileView, AgentProfileListResponse +from browser_use_sdk.types import AgentProfileView, AgentProfileListResponse ``` Methods: -- client.agent_profiles.create(\*\*params) -> AgentProfileView -- client.agent_profiles.retrieve(profile_id) -> AgentProfileView -- client.agent_profiles.update(profile_id, \*\*params) -> AgentProfileView -- client.agent_profiles.list(\*\*params) -> AgentProfileListResponse -- client.agent_profiles.delete(profile_id) -> object +- client.agent_profiles.create(\*\*params) -> AgentProfileView +- client.agent_profiles.retrieve(profile_id) -> AgentProfileView +- client.agent_profiles.update(profile_id, \*\*params) -> AgentProfileView +- client.agent_profiles.list(\*\*params) -> AgentProfileListResponse +- client.agent_profiles.delete(profile_id) -> None diff --git a/mypy.ini b/mypy.ini index a4a2b13..d128e00 100644 --- a/mypy.ini +++ b/mypy.ini @@ -8,7 +8,7 @@ show_error_codes = True # # We also exclude our `tests` as mypy doesn't always infer # types correctly and Pyright will still catch any type errors. -exclude = ^(src/browser_use/_files\.py|_dev/.*\.py|tests/.*)$ +exclude = ^(src/browser_use_sdk/_files\.py|_dev/.*\.py|tests/.*)$ strict_equality = True implicit_reexport = True diff --git a/pyproject.toml b/pyproject.toml index a690c81..d50d931 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "browser-use-sdk" -version = "0.0.2" +version = "0.1.0" description = "The official Python library for the browser-use API" dynamic = ["readme"] license = "Apache-2.0" @@ -79,14 +79,14 @@ format = { chain = [ "check:ruff" = "ruff check ." "fix:ruff" = "ruff check --fix ." -"check:importable" = "python -c 'import browser_use'" +"check:importable" = "python -c 'import browser_use_sdk'" typecheck = { chain = [ "typecheck:pyright", "typecheck:mypy" ]} "typecheck:pyright" = "pyright" -"typecheck:verify-types" = "pyright --verifytypes browser_use --ignoreexternal" +"typecheck:verify-types" = "pyright --verifytypes browser_use_sdk --ignoreexternal" "typecheck:mypy" = "mypy ." [build-system] @@ -99,7 +99,7 @@ include = [ ] [tool.hatch.build.targets.wheel] -packages = ["src/browser_use"] +packages = ["src/browser_use_sdk"] [tool.hatch.build.targets.sdist] # Basically everything except hidden files/directories (such as .github, .devcontainers, .python-version, etc) @@ -202,7 +202,7 @@ length-sort = true length-sort-straight = true combine-as-imports = true extra-standard-library = ["typing_extensions"] -known-first-party = ["browser_use", "tests"] +known-first-party = ["browser_use_sdk", "tests"] [tool.ruff.lint.per-file-ignores] "bin/**.py" = ["T201", "T203"] diff --git a/release-please-config.json b/release-please-config.json index 7fdd77c..1225639 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -61,6 +61,6 @@ ], "release-type": "python", "extra-files": [ - "src/browser_use/_version.py" + "src/browser_use_sdk/_version.py" ] } \ No newline at end of file diff --git a/scripts/lint b/scripts/lint index dbaef9a..3094ad3 100755 --- a/scripts/lint +++ b/scripts/lint @@ -8,4 +8,4 @@ echo "==> Running lints" rye run lint echo "==> Making sure it imports" -rye run python -c 'import browser_use' +rye run python -c 'import browser_use_sdk' diff --git a/src/browser_use/types/session_list_response.py b/src/browser_use/types/session_list_response.py deleted file mode 100644 index ed6951c..0000000 --- a/src/browser_use/types/session_list_response.py +++ /dev/null @@ -1,20 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List - -from pydantic import Field as FieldInfo - -from .._models import BaseModel -from .session_view import SessionView - -__all__ = ["SessionListResponse"] - - -class SessionListResponse(BaseModel): - items: List[SessionView] - - page_number: int = FieldInfo(alias="pageNumber") - - page_size: int = FieldInfo(alias="pageSize") - - total_items: int = FieldInfo(alias="totalItems") diff --git a/src/browser_use/types/session_retrieve_params.py b/src/browser_use/types/session_retrieve_params.py deleted file mode 100644 index 33db5d3..0000000 --- a/src/browser_use/types/session_retrieve_params.py +++ /dev/null @@ -1,13 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Annotated, TypedDict - -from .._utils import PropertyInfo - -__all__ = ["SessionRetrieveParams"] - - -class SessionRetrieveParams(TypedDict, total=False): - include_tasks: Annotated[bool, PropertyInfo(alias="includeTasks")] diff --git a/src/browser_use/types/task_list_params.py b/src/browser_use/types/task_list_params.py deleted file mode 100644 index f354c46..0000000 --- a/src/browser_use/types/task_list_params.py +++ /dev/null @@ -1,21 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Annotated, TypedDict - -from .._utils import PropertyInfo - -__all__ = ["TaskListParams"] - - -class TaskListParams(TypedDict, total=False): - include_output_files: Annotated[bool, PropertyInfo(alias="includeOutputFiles")] - - include_steps: Annotated[bool, PropertyInfo(alias="includeSteps")] - - include_user_uploaded_files: Annotated[bool, PropertyInfo(alias="includeUserUploadedFiles")] - - page_number: Annotated[int, PropertyInfo(alias="pageNumber")] - - page_size: Annotated[int, PropertyInfo(alias="pageSize")] diff --git a/src/browser_use/types/task_retrieve_params.py b/src/browser_use/types/task_retrieve_params.py deleted file mode 100644 index dc8e594..0000000 --- a/src/browser_use/types/task_retrieve_params.py +++ /dev/null @@ -1,13 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Annotated, TypedDict - -from .._utils import PropertyInfo - -__all__ = ["TaskRetrieveParams"] - - -class TaskRetrieveParams(TypedDict, total=False): - status_only: Annotated[bool, PropertyInfo(alias="statusOnly")] diff --git a/src/browser_use/types/task_retrieve_response.py b/src/browser_use/types/task_retrieve_response.py deleted file mode 100644 index fac9792..0000000 --- a/src/browser_use/types/task_retrieve_response.py +++ /dev/null @@ -1,23 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Union -from typing_extensions import TypeAlias - -from .._models import BaseModel -from .task_view import TaskView -from .task_status import TaskStatus - -__all__ = ["TaskRetrieveResponse", "TaskStatusView"] - - -class TaskStatusView(BaseModel): - status: TaskStatus - """Enumeration of possible task execution states - - Attributes: STARTED: Task has been initiated and is currently running PAUSED: - Task execution has been temporarily paused STOPPED: Task execution has been - stopped (not completed) FINISHED: Task has completed successfully - """ - - -TaskRetrieveResponse: TypeAlias = Union[TaskView, TaskStatusView] diff --git a/src/browser_use/types/task_view.py b/src/browser_use/types/task_view.py deleted file mode 100644 index 933ceb5..0000000 --- a/src/browser_use/types/task_view.py +++ /dev/null @@ -1,66 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Dict, List, Optional -from datetime import datetime - -from pydantic import Field as FieldInfo - -from .._models import BaseModel -from .llm_model import LlmModel -from .task_status import TaskStatus - -__all__ = ["TaskView", "Step"] - - -class Step(BaseModel): - actions: List[str] - - evaluation_previous_goal: str = FieldInfo(alias="evaluationPreviousGoal") - - memory: str - - next_goal: str = FieldInfo(alias="nextGoal") - - number: int - - url: str - - screenshot_url: Optional[str] = FieldInfo(alias="screenshotUrl", default=None) - - -class TaskView(BaseModel): - id: str - - done_output: str = FieldInfo(alias="doneOutput") - - is_scheduled: bool = FieldInfo(alias="isScheduled") - - llm: LlmModel - - session_id: str = FieldInfo(alias="sessionId") - - started_at: datetime = FieldInfo(alias="startedAt") - - status: TaskStatus - """Enumeration of possible task execution states - - Attributes: STARTED: Task has been initiated and is currently running PAUSED: - Task execution has been temporarily paused STOPPED: Task execution has been - stopped (not completed) FINISHED: Task has completed successfully - """ - - task: str - - browser_use_version: Optional[str] = FieldInfo(alias="browserUseVersion", default=None) - - finished_at: Optional[datetime] = FieldInfo(alias="finishedAt", default=None) - - metadata: Optional[Dict[str, object]] = None - - output_files: Optional[List[str]] = FieldInfo(alias="outputFiles", default=None) - - session_live_url: Optional[str] = FieldInfo(alias="sessionLiveUrl", default=None) - - steps: Optional[List[Step]] = None - - user_uploaded_files: Optional[List[str]] = FieldInfo(alias="userUploadedFiles", default=None) diff --git a/src/browser_use/__init__.py b/src/browser_use_sdk/__init__.py similarity index 94% rename from src/browser_use/__init__.py rename to src/browser_use_sdk/__init__.py index be0c71c..235c0b0 100644 --- a/src/browser_use/__init__.py +++ b/src/browser_use_sdk/__init__.py @@ -89,12 +89,12 @@ # Update the __module__ attribute for exported symbols so that # error messages point to this module instead of the module # it was originally defined in, e.g. -# browser_use._exceptions.NotFoundError -> browser_use.NotFoundError +# browser_use_sdk._exceptions.NotFoundError -> browser_use_sdk.NotFoundError __locals = locals() for __name in __all__: if not __name.startswith("__"): try: - __locals[__name].__module__ = "browser_use" + __locals[__name].__module__ = "browser_use_sdk" except (TypeError, AttributeError): # Some of our exported symbols are builtins which we can't set attributes for. pass diff --git a/src/browser_use/_base_client.py b/src/browser_use_sdk/_base_client.py similarity index 99% rename from src/browser_use/_base_client.py rename to src/browser_use_sdk/_base_client.py index 0c7b43b..f182716 100644 --- a/src/browser_use/_base_client.py +++ b/src/browser_use_sdk/_base_client.py @@ -389,7 +389,7 @@ def __init__( if max_retries is None: # pyright: ignore[reportUnnecessaryComparison] raise TypeError( - "max_retries cannot be None. If you want to disable retries, pass `0`; if you want unlimited retries, pass `math.inf` or a very high number; if you want the default behavior, pass `browser_use.DEFAULT_MAX_RETRIES`" + "max_retries cannot be None. If you want to disable retries, pass `0`; if you want unlimited retries, pass `math.inf` or a very high number; if you want the default behavior, pass `browser_use_sdk.DEFAULT_MAX_RETRIES`" ) def _enforce_trailing_slash(self, url: URL) -> URL: diff --git a/src/browser_use/_client.py b/src/browser_use_sdk/_client.py similarity index 97% rename from src/browser_use/_client.py rename to src/browser_use_sdk/_client.py index 2c3f8fc..13ad53e 100644 --- a/src/browser_use/_client.py +++ b/src/browser_use_sdk/_client.py @@ -29,6 +29,7 @@ SyncAPIClient, AsyncAPIClient, ) +from .resources.users import users from .resources.sessions import sessions __all__ = [ @@ -44,6 +45,7 @@ class BrowserUse(SyncAPIClient): + users: users.UsersResource tasks: tasks.TasksResource sessions: sessions.SessionsResource browser_profiles: browser_profiles.BrowserProfilesResource @@ -105,6 +107,7 @@ def __init__( _strict_response_validation=_strict_response_validation, ) + self.users = users.UsersResource(self) self.tasks = tasks.TasksResource(self) self.sessions = sessions.SessionsResource(self) self.browser_profiles = browser_profiles.BrowserProfilesResource(self) @@ -218,6 +221,7 @@ def _make_status_error( class AsyncBrowserUse(AsyncAPIClient): + users: users.AsyncUsersResource tasks: tasks.AsyncTasksResource sessions: sessions.AsyncSessionsResource browser_profiles: browser_profiles.AsyncBrowserProfilesResource @@ -279,6 +283,7 @@ def __init__( _strict_response_validation=_strict_response_validation, ) + self.users = users.AsyncUsersResource(self) self.tasks = tasks.AsyncTasksResource(self) self.sessions = sessions.AsyncSessionsResource(self) self.browser_profiles = browser_profiles.AsyncBrowserProfilesResource(self) @@ -393,6 +398,7 @@ def _make_status_error( class BrowserUseWithRawResponse: def __init__(self, client: BrowserUse) -> None: + self.users = users.UsersResourceWithRawResponse(client.users) self.tasks = tasks.TasksResourceWithRawResponse(client.tasks) self.sessions = sessions.SessionsResourceWithRawResponse(client.sessions) self.browser_profiles = browser_profiles.BrowserProfilesResourceWithRawResponse(client.browser_profiles) @@ -401,6 +407,7 @@ def __init__(self, client: BrowserUse) -> None: class AsyncBrowserUseWithRawResponse: def __init__(self, client: AsyncBrowserUse) -> None: + self.users = users.AsyncUsersResourceWithRawResponse(client.users) self.tasks = tasks.AsyncTasksResourceWithRawResponse(client.tasks) self.sessions = sessions.AsyncSessionsResourceWithRawResponse(client.sessions) self.browser_profiles = browser_profiles.AsyncBrowserProfilesResourceWithRawResponse(client.browser_profiles) @@ -409,6 +416,7 @@ def __init__(self, client: AsyncBrowserUse) -> None: class BrowserUseWithStreamedResponse: def __init__(self, client: BrowserUse) -> None: + self.users = users.UsersResourceWithStreamingResponse(client.users) self.tasks = tasks.TasksResourceWithStreamingResponse(client.tasks) self.sessions = sessions.SessionsResourceWithStreamingResponse(client.sessions) self.browser_profiles = browser_profiles.BrowserProfilesResourceWithStreamingResponse(client.browser_profiles) @@ -417,6 +425,7 @@ def __init__(self, client: BrowserUse) -> None: class AsyncBrowserUseWithStreamedResponse: def __init__(self, client: AsyncBrowserUse) -> None: + self.users = users.AsyncUsersResourceWithStreamingResponse(client.users) self.tasks = tasks.AsyncTasksResourceWithStreamingResponse(client.tasks) self.sessions = sessions.AsyncSessionsResourceWithStreamingResponse(client.sessions) self.browser_profiles = browser_profiles.AsyncBrowserProfilesResourceWithStreamingResponse( diff --git a/src/browser_use/_compat.py b/src/browser_use_sdk/_compat.py similarity index 100% rename from src/browser_use/_compat.py rename to src/browser_use_sdk/_compat.py diff --git a/src/browser_use/_constants.py b/src/browser_use_sdk/_constants.py similarity index 100% rename from src/browser_use/_constants.py rename to src/browser_use_sdk/_constants.py diff --git a/src/browser_use/_exceptions.py b/src/browser_use_sdk/_exceptions.py similarity index 100% rename from src/browser_use/_exceptions.py rename to src/browser_use_sdk/_exceptions.py diff --git a/src/browser_use/_files.py b/src/browser_use_sdk/_files.py similarity index 100% rename from src/browser_use/_files.py rename to src/browser_use_sdk/_files.py diff --git a/src/browser_use/_models.py b/src/browser_use_sdk/_models.py similarity index 100% rename from src/browser_use/_models.py rename to src/browser_use_sdk/_models.py diff --git a/src/browser_use/_qs.py b/src/browser_use_sdk/_qs.py similarity index 100% rename from src/browser_use/_qs.py rename to src/browser_use_sdk/_qs.py diff --git a/src/browser_use/_resource.py b/src/browser_use_sdk/_resource.py similarity index 100% rename from src/browser_use/_resource.py rename to src/browser_use_sdk/_resource.py diff --git a/src/browser_use/_response.py b/src/browser_use_sdk/_response.py similarity index 99% rename from src/browser_use/_response.py rename to src/browser_use_sdk/_response.py index 183a4c8..28a84a0 100644 --- a/src/browser_use/_response.py +++ b/src/browser_use_sdk/_response.py @@ -218,7 +218,7 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T: and issubclass(origin, pydantic.BaseModel) ): raise TypeError( - "Pydantic models must subclass our base model type, e.g. `from browser_use import BaseModel`" + "Pydantic models must subclass our base model type, e.g. `from browser_use_sdk import BaseModel`" ) if ( @@ -285,7 +285,7 @@ def parse(self, *, to: type[_T] | None = None) -> R | _T: the `to` argument, e.g. ```py - from browser_use import BaseModel + from browser_use_sdk import BaseModel class MyModel(BaseModel): @@ -387,7 +387,7 @@ async def parse(self, *, to: type[_T] | None = None) -> R | _T: the `to` argument, e.g. ```py - from browser_use import BaseModel + from browser_use_sdk import BaseModel class MyModel(BaseModel): @@ -558,7 +558,7 @@ async def stream_to_file( class MissingStreamClassError(TypeError): def __init__(self) -> None: super().__init__( - "The `stream` argument was set to `True` but the `stream_cls` argument was not given. See `browser_use._streaming` for reference", + "The `stream` argument was set to `True` but the `stream_cls` argument was not given. See `browser_use_sdk._streaming` for reference", ) diff --git a/src/browser_use/_streaming.py b/src/browser_use_sdk/_streaming.py similarity index 100% rename from src/browser_use/_streaming.py rename to src/browser_use_sdk/_streaming.py diff --git a/src/browser_use/_types.py b/src/browser_use_sdk/_types.py similarity index 99% rename from src/browser_use/_types.py rename to src/browser_use_sdk/_types.py index 8d1aae8..450c5bb 100644 --- a/src/browser_use/_types.py +++ b/src/browser_use_sdk/_types.py @@ -81,7 +81,7 @@ # This unfortunately means that you will either have # to import this type and pass it explicitly: # -# from browser_use import NoneType +# from browser_use_sdk import NoneType # client.get('/foo', cast_to=NoneType) # # or build it yourself: diff --git a/src/browser_use/_utils/__init__.py b/src/browser_use_sdk/_utils/__init__.py similarity index 100% rename from src/browser_use/_utils/__init__.py rename to src/browser_use_sdk/_utils/__init__.py diff --git a/src/browser_use/_utils/_logs.py b/src/browser_use_sdk/_utils/_logs.py similarity index 75% rename from src/browser_use/_utils/_logs.py rename to src/browser_use_sdk/_utils/_logs.py index f37e60c..8398493 100644 --- a/src/browser_use/_utils/_logs.py +++ b/src/browser_use_sdk/_utils/_logs.py @@ -1,12 +1,12 @@ import os import logging -logger: logging.Logger = logging.getLogger("browser_use") +logger: logging.Logger = logging.getLogger("browser_use_sdk") httpx_logger: logging.Logger = logging.getLogger("httpx") def _basic_config() -> None: - # e.g. [2023-10-05 14:12:26 - browser_use._base_client:818 - DEBUG] HTTP Request: POST http://127.0.0.1:4010/foo/bar "200 OK" + # e.g. [2023-10-05 14:12:26 - browser_use_sdk._base_client:818 - DEBUG] HTTP Request: POST http://127.0.0.1:4010/foo/bar "200 OK" logging.basicConfig( format="[%(asctime)s - %(name)s:%(lineno)d - %(levelname)s] %(message)s", datefmt="%Y-%m-%d %H:%M:%S", diff --git a/src/browser_use/_utils/_proxy.py b/src/browser_use_sdk/_utils/_proxy.py similarity index 100% rename from src/browser_use/_utils/_proxy.py rename to src/browser_use_sdk/_utils/_proxy.py diff --git a/src/browser_use/_utils/_reflection.py b/src/browser_use_sdk/_utils/_reflection.py similarity index 100% rename from src/browser_use/_utils/_reflection.py rename to src/browser_use_sdk/_utils/_reflection.py diff --git a/src/browser_use/_utils/_resources_proxy.py b/src/browser_use_sdk/_utils/_resources_proxy.py similarity index 50% rename from src/browser_use/_utils/_resources_proxy.py rename to src/browser_use_sdk/_utils/_resources_proxy.py index 6618037..9451692 100644 --- a/src/browser_use/_utils/_resources_proxy.py +++ b/src/browser_use_sdk/_utils/_resources_proxy.py @@ -7,17 +7,17 @@ class ResourcesProxy(LazyProxy[Any]): - """A proxy for the `browser_use.resources` module. + """A proxy for the `browser_use_sdk.resources` module. - This is used so that we can lazily import `browser_use.resources` only when - needed *and* so that users can just import `browser_use` and reference `browser_use.resources` + This is used so that we can lazily import `browser_use_sdk.resources` only when + needed *and* so that users can just import `browser_use_sdk` and reference `browser_use_sdk.resources` """ @override def __load__(self) -> Any: import importlib - mod = importlib.import_module("browser_use.resources") + mod = importlib.import_module("browser_use_sdk.resources") return mod diff --git a/src/browser_use/_utils/_streams.py b/src/browser_use_sdk/_utils/_streams.py similarity index 100% rename from src/browser_use/_utils/_streams.py rename to src/browser_use_sdk/_utils/_streams.py diff --git a/src/browser_use/_utils/_sync.py b/src/browser_use_sdk/_utils/_sync.py similarity index 100% rename from src/browser_use/_utils/_sync.py rename to src/browser_use_sdk/_utils/_sync.py diff --git a/src/browser_use/_utils/_transform.py b/src/browser_use_sdk/_utils/_transform.py similarity index 100% rename from src/browser_use/_utils/_transform.py rename to src/browser_use_sdk/_utils/_transform.py diff --git a/src/browser_use/_utils/_typing.py b/src/browser_use_sdk/_utils/_typing.py similarity index 100% rename from src/browser_use/_utils/_typing.py rename to src/browser_use_sdk/_utils/_typing.py diff --git a/src/browser_use/_utils/_utils.py b/src/browser_use_sdk/_utils/_utils.py similarity index 100% rename from src/browser_use/_utils/_utils.py rename to src/browser_use_sdk/_utils/_utils.py diff --git a/src/browser_use_sdk/_version.py b/src/browser_use_sdk/_version.py new file mode 100644 index 0000000..86ea4c5 --- /dev/null +++ b/src/browser_use_sdk/_version.py @@ -0,0 +1,4 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +__title__ = "browser_use_sdk" +__version__ = "0.1.0" # x-release-please-version diff --git a/src/browser_use_sdk/lib/.keep b/src/browser_use_sdk/lib/.keep new file mode 100644 index 0000000..5e2c99f --- /dev/null +++ b/src/browser_use_sdk/lib/.keep @@ -0,0 +1,4 @@ +File generated from our OpenAPI spec by Stainless. + +This directory can be used to store custom files to expand the SDK. +It is ignored by Stainless code generation and its content (other than this keep file) won't be touched. \ No newline at end of file diff --git a/src/browser_use/py.typed b/src/browser_use_sdk/py.typed similarity index 100% rename from src/browser_use/py.typed rename to src/browser_use_sdk/py.typed diff --git a/src/browser_use/resources/__init__.py b/src/browser_use_sdk/resources/__init__.py similarity index 82% rename from src/browser_use/resources/__init__.py rename to src/browser_use_sdk/resources/__init__.py index 02bbbb2..c8d13bb 100644 --- a/src/browser_use/resources/__init__.py +++ b/src/browser_use_sdk/resources/__init__.py @@ -8,6 +8,14 @@ TasksResourceWithStreamingResponse, AsyncTasksResourceWithStreamingResponse, ) +from .users import ( + UsersResource, + AsyncUsersResource, + UsersResourceWithRawResponse, + AsyncUsersResourceWithRawResponse, + UsersResourceWithStreamingResponse, + AsyncUsersResourceWithStreamingResponse, +) from .sessions import ( SessionsResource, AsyncSessionsResource, @@ -34,6 +42,12 @@ ) __all__ = [ + "UsersResource", + "AsyncUsersResource", + "UsersResourceWithRawResponse", + "AsyncUsersResourceWithRawResponse", + "UsersResourceWithStreamingResponse", + "AsyncUsersResourceWithStreamingResponse", "TasksResource", "AsyncTasksResource", "TasksResourceWithRawResponse", diff --git a/src/browser_use/resources/agent_profiles.py b/src/browser_use_sdk/resources/agent_profiles.py similarity index 76% rename from src/browser_use/resources/agent_profiles.py rename to src/browser_use_sdk/resources/agent_profiles.py index 2d78b3a..b596dbc 100644 --- a/src/browser_use/resources/agent_profiles.py +++ b/src/browser_use_sdk/resources/agent_profiles.py @@ -7,7 +7,7 @@ import httpx from ..types import agent_profile_list_params, agent_profile_create_params, agent_profile_update_params -from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from .._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven from .._utils import maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource @@ -49,11 +49,11 @@ def create( *, name: str, allowed_domains: List[str] | NotGiven = NOT_GIVEN, + custom_system_prompt_extension: str | NotGiven = NOT_GIVEN, description: str | NotGiven = NOT_GIVEN, flash_mode: bool | NotGiven = NOT_GIVEN, highlight_elements: bool | NotGiven = NOT_GIVEN, max_agent_steps: int | NotGiven = NOT_GIVEN, - system_prompt: str | NotGiven = NOT_GIVEN, thinking: bool | NotGiven = NOT_GIVEN, vision: bool | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -64,7 +64,34 @@ def create( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AgentProfileView: """ - Create Agent Profile + Create a new agent profile for the authenticated user. + + Agent profiles define how your AI agents behave during tasks. You can create + multiple profiles for different use cases (e.g., customer support, data + analysis, web scraping). Free users can create 1 profile; paid users can create + unlimited profiles. + + Key features you can configure: + + - System prompt: The core instructions that define the agent's personality and + behavior + - Allowed domains: Restrict which websites the agent can access + - Max steps: Limit how many actions the agent can take in a single task + - Vision: Enable/disable the agent's ability to see and analyze screenshots + - Thinking: Enable/disable the agent's reasoning process + + Args: + + - request: The agent profile configuration including name, description, and + behavior settings + + Returns: + + - The newly created agent profile with all its details + + Raises: + + - 402: If user needs a subscription to create additional profiles Args: extra_headers: Send extra headers @@ -81,11 +108,11 @@ def create( { "name": name, "allowed_domains": allowed_domains, + "custom_system_prompt_extension": custom_system_prompt_extension, "description": description, "flash_mode": flash_mode, "highlight_elements": highlight_elements, "max_agent_steps": max_agent_steps, - "system_prompt": system_prompt, "thinking": thinking, "vision": vision, }, @@ -109,7 +136,22 @@ def retrieve( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AgentProfileView: """ - Get Agent Profile + Get a specific agent profile by its ID. + + Retrieves the complete details of an agent profile, including all its + configuration settings like system prompts, allowed domains, and behavior flags. + + Args: + + - profile_id: The unique identifier of the agent profile + + Returns: + + - Complete agent profile information + + Raises: + + - 404: If the user agent profile doesn't exist Args: extra_headers: Send extra headers @@ -135,12 +177,12 @@ def update( profile_id: str, *, allowed_domains: Optional[List[str]] | NotGiven = NOT_GIVEN, + custom_system_prompt_extension: Optional[str] | NotGiven = NOT_GIVEN, description: Optional[str] | NotGiven = NOT_GIVEN, flash_mode: Optional[bool] | NotGiven = NOT_GIVEN, highlight_elements: Optional[bool] | NotGiven = NOT_GIVEN, max_agent_steps: Optional[int] | NotGiven = NOT_GIVEN, name: Optional[str] | NotGiven = NOT_GIVEN, - system_prompt: Optional[str] | NotGiven = NOT_GIVEN, thinking: Optional[bool] | NotGiven = NOT_GIVEN, vision: Optional[bool] | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -151,7 +193,24 @@ def update( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AgentProfileView: """ - Update Agent Profile + Update an existing agent profile. + + Modify any aspect of an agent profile, such as its name, description, system + prompt, or behavior settings. Only the fields you provide will be updated; other + fields remain unchanged. + + Args: + + - profile_id: The unique identifier of the agent profile to update + - request: The fields to update (only provided fields will be changed) + + Returns: + + - The updated agent profile with all its current details + + Raises: + + - 404: If the user agent profile doesn't exist Args: extra_headers: Send extra headers @@ -169,12 +228,12 @@ def update( body=maybe_transform( { "allowed_domains": allowed_domains, + "custom_system_prompt_extension": custom_system_prompt_extension, "description": description, "flash_mode": flash_mode, "highlight_elements": highlight_elements, "max_agent_steps": max_agent_steps, "name": name, - "system_prompt": system_prompt, "thinking": thinking, "vision": vision, }, @@ -199,7 +258,17 @@ def list( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AgentProfileListResponse: """ - List Agent Profiles + Get a paginated list of all agent profiles for the authenticated user. + + Agent profiles define how your AI agents behave, including their personality, + capabilities, and limitations. Use this endpoint to see all your configured + agent profiles. + + Returns: + + - A paginated list of agent profiles + - Total count of profiles + - Page information for navigation Args: extra_headers: Send extra headers @@ -238,9 +307,21 @@ def delete( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> object: + ) -> None: """ - Delete Agent Profile + Delete an agent profile. + + Permanently removes an agent profile and all its configuration. This action + cannot be undone. Any tasks that were using this profile will continue to work, + but you won't be able to create new tasks with the deleted profile. + + Args: + + - profile_id: The unique identifier of the agent profile to delete + + Returns: + + - 204 No Content on successful deletion (idempotent) Args: extra_headers: Send extra headers @@ -253,12 +334,13 @@ def delete( """ if not profile_id: raise ValueError(f"Expected a non-empty value for `profile_id` but received {profile_id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} return self._delete( f"/agent-profiles/{profile_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=object, + cast_to=NoneType, ) @@ -287,11 +369,11 @@ async def create( *, name: str, allowed_domains: List[str] | NotGiven = NOT_GIVEN, + custom_system_prompt_extension: str | NotGiven = NOT_GIVEN, description: str | NotGiven = NOT_GIVEN, flash_mode: bool | NotGiven = NOT_GIVEN, highlight_elements: bool | NotGiven = NOT_GIVEN, max_agent_steps: int | NotGiven = NOT_GIVEN, - system_prompt: str | NotGiven = NOT_GIVEN, thinking: bool | NotGiven = NOT_GIVEN, vision: bool | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -302,7 +384,34 @@ async def create( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AgentProfileView: """ - Create Agent Profile + Create a new agent profile for the authenticated user. + + Agent profiles define how your AI agents behave during tasks. You can create + multiple profiles for different use cases (e.g., customer support, data + analysis, web scraping). Free users can create 1 profile; paid users can create + unlimited profiles. + + Key features you can configure: + + - System prompt: The core instructions that define the agent's personality and + behavior + - Allowed domains: Restrict which websites the agent can access + - Max steps: Limit how many actions the agent can take in a single task + - Vision: Enable/disable the agent's ability to see and analyze screenshots + - Thinking: Enable/disable the agent's reasoning process + + Args: + + - request: The agent profile configuration including name, description, and + behavior settings + + Returns: + + - The newly created agent profile with all its details + + Raises: + + - 402: If user needs a subscription to create additional profiles Args: extra_headers: Send extra headers @@ -319,11 +428,11 @@ async def create( { "name": name, "allowed_domains": allowed_domains, + "custom_system_prompt_extension": custom_system_prompt_extension, "description": description, "flash_mode": flash_mode, "highlight_elements": highlight_elements, "max_agent_steps": max_agent_steps, - "system_prompt": system_prompt, "thinking": thinking, "vision": vision, }, @@ -347,7 +456,22 @@ async def retrieve( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AgentProfileView: """ - Get Agent Profile + Get a specific agent profile by its ID. + + Retrieves the complete details of an agent profile, including all its + configuration settings like system prompts, allowed domains, and behavior flags. + + Args: + + - profile_id: The unique identifier of the agent profile + + Returns: + + - Complete agent profile information + + Raises: + + - 404: If the user agent profile doesn't exist Args: extra_headers: Send extra headers @@ -373,12 +497,12 @@ async def update( profile_id: str, *, allowed_domains: Optional[List[str]] | NotGiven = NOT_GIVEN, + custom_system_prompt_extension: Optional[str] | NotGiven = NOT_GIVEN, description: Optional[str] | NotGiven = NOT_GIVEN, flash_mode: Optional[bool] | NotGiven = NOT_GIVEN, highlight_elements: Optional[bool] | NotGiven = NOT_GIVEN, max_agent_steps: Optional[int] | NotGiven = NOT_GIVEN, name: Optional[str] | NotGiven = NOT_GIVEN, - system_prompt: Optional[str] | NotGiven = NOT_GIVEN, thinking: Optional[bool] | NotGiven = NOT_GIVEN, vision: Optional[bool] | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -389,7 +513,24 @@ async def update( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AgentProfileView: """ - Update Agent Profile + Update an existing agent profile. + + Modify any aspect of an agent profile, such as its name, description, system + prompt, or behavior settings. Only the fields you provide will be updated; other + fields remain unchanged. + + Args: + + - profile_id: The unique identifier of the agent profile to update + - request: The fields to update (only provided fields will be changed) + + Returns: + + - The updated agent profile with all its current details + + Raises: + + - 404: If the user agent profile doesn't exist Args: extra_headers: Send extra headers @@ -407,12 +548,12 @@ async def update( body=await async_maybe_transform( { "allowed_domains": allowed_domains, + "custom_system_prompt_extension": custom_system_prompt_extension, "description": description, "flash_mode": flash_mode, "highlight_elements": highlight_elements, "max_agent_steps": max_agent_steps, "name": name, - "system_prompt": system_prompt, "thinking": thinking, "vision": vision, }, @@ -437,7 +578,17 @@ async def list( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AgentProfileListResponse: """ - List Agent Profiles + Get a paginated list of all agent profiles for the authenticated user. + + Agent profiles define how your AI agents behave, including their personality, + capabilities, and limitations. Use this endpoint to see all your configured + agent profiles. + + Returns: + + - A paginated list of agent profiles + - Total count of profiles + - Page information for navigation Args: extra_headers: Send extra headers @@ -476,9 +627,21 @@ async def delete( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> object: + ) -> None: """ - Delete Agent Profile + Delete an agent profile. + + Permanently removes an agent profile and all its configuration. This action + cannot be undone. Any tasks that were using this profile will continue to work, + but you won't be able to create new tasks with the deleted profile. + + Args: + + - profile_id: The unique identifier of the agent profile to delete + + Returns: + + - 204 No Content on successful deletion (idempotent) Args: extra_headers: Send extra headers @@ -491,12 +654,13 @@ async def delete( """ if not profile_id: raise ValueError(f"Expected a non-empty value for `profile_id` but received {profile_id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} return await self._delete( f"/agent-profiles/{profile_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=object, + cast_to=NoneType, ) diff --git a/src/browser_use/resources/browser_profiles.py b/src/browser_use_sdk/resources/browser_profiles.py similarity index 77% rename from src/browser_use/resources/browser_profiles.py rename to src/browser_use_sdk/resources/browser_profiles.py index 74befe1..3a8b417 100644 --- a/src/browser_use/resources/browser_profiles.py +++ b/src/browser_use_sdk/resources/browser_profiles.py @@ -12,7 +12,7 @@ browser_profile_create_params, browser_profile_update_params, ) -from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from .._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven from .._utils import maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource @@ -71,7 +71,33 @@ def create( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> BrowserProfileView: """ - Create Browser Profile + Create a new browser profile for the authenticated user. + + Browser profiles define how your web browsers behave during AI agent tasks. You + can create multiple profiles for different use cases (e.g., mobile testing, + desktop browsing, proxy-enabled scraping). Free users can create up to 10 + profiles; paid users can create unlimited profiles. + + Key features you can configure: + + - Viewport dimensions: Set the browser window size for consistent rendering + - Mobile emulation: Enable mobile device simulation + - Proxy settings: Route traffic through specific locations or proxy servers + - Ad blocking: Enable/disable ad blocking for cleaner browsing + - Cache persistence: Choose whether to save browser data between sessions + + Args: + + - request: The browser profile configuration including name, description, and + browser settings + + Returns: + + - The newly created browser profile with all its details + + Raises: + + - 402: If user needs a subscription to create additional profiles Args: extra_headers: Send extra headers @@ -117,7 +143,23 @@ def retrieve( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> BrowserProfileView: """ - Get Browser Profile + Get a specific browser profile by its ID. + + Retrieves the complete details of a browser profile, including all its + configuration settings like viewport dimensions, proxy settings, and behavior + flags. + + Args: + + - profile_id: The unique identifier of the browser profile + + Returns: + + - Complete browser profile information + + Raises: + + - 404: If the user browser profile doesn't exist Args: extra_headers: Send extra headers @@ -160,7 +202,24 @@ def update( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> BrowserProfileView: """ - Update Browser Profile + Update an existing browser profile. + + Modify any aspect of a browser profile, such as its name, description, viewport + settings, or proxy configuration. Only the fields you provide will be updated; + other fields remain unchanged. + + Args: + + - profile_id: The unique identifier of the browser profile to update + - request: The fields to update (only provided fields will be changed) + + Returns: + + - The updated browser profile with all its current details + + Raises: + + - 404: If the user browser profile doesn't exist Args: extra_headers: Send extra headers @@ -209,7 +268,17 @@ def list( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> BrowserProfileListResponse: """ - List Browser Profiles + Get a paginated list of all browser profiles for the authenticated user. + + Browser profiles define how your web browsers behave during AI agent tasks, + including settings like viewport size, mobile emulation, proxy configuration, + and ad blocking. Use this endpoint to see all your configured browser profiles. + + Returns: + + - A paginated list of browser profiles + - Total count of profiles + - Page information for navigation Args: extra_headers: Send extra headers @@ -248,9 +317,22 @@ def delete( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> object: + ) -> None: """ - Delete Browser Profile + Delete a browser profile. + + Permanently removes a browser profile and all its configuration. This action + cannot be undone. The profile will also be removed from the browser service. Any + active sessions using this profile will continue to work, but you won't be able + to create new sessions with the deleted profile. + + Args: + + - profile_id: The unique identifier of the browser profile to delete + + Returns: + + - 204 No Content on successful deletion (idempotent) Args: extra_headers: Send extra headers @@ -263,12 +345,13 @@ def delete( """ if not profile_id: raise ValueError(f"Expected a non-empty value for `profile_id` but received {profile_id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} return self._delete( f"/browser-profiles/{profile_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=object, + cast_to=NoneType, ) @@ -313,7 +396,33 @@ async def create( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> BrowserProfileView: """ - Create Browser Profile + Create a new browser profile for the authenticated user. + + Browser profiles define how your web browsers behave during AI agent tasks. You + can create multiple profiles for different use cases (e.g., mobile testing, + desktop browsing, proxy-enabled scraping). Free users can create up to 10 + profiles; paid users can create unlimited profiles. + + Key features you can configure: + + - Viewport dimensions: Set the browser window size for consistent rendering + - Mobile emulation: Enable mobile device simulation + - Proxy settings: Route traffic through specific locations or proxy servers + - Ad blocking: Enable/disable ad blocking for cleaner browsing + - Cache persistence: Choose whether to save browser data between sessions + + Args: + + - request: The browser profile configuration including name, description, and + browser settings + + Returns: + + - The newly created browser profile with all its details + + Raises: + + - 402: If user needs a subscription to create additional profiles Args: extra_headers: Send extra headers @@ -359,7 +468,23 @@ async def retrieve( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> BrowserProfileView: """ - Get Browser Profile + Get a specific browser profile by its ID. + + Retrieves the complete details of a browser profile, including all its + configuration settings like viewport dimensions, proxy settings, and behavior + flags. + + Args: + + - profile_id: The unique identifier of the browser profile + + Returns: + + - Complete browser profile information + + Raises: + + - 404: If the user browser profile doesn't exist Args: extra_headers: Send extra headers @@ -402,7 +527,24 @@ async def update( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> BrowserProfileView: """ - Update Browser Profile + Update an existing browser profile. + + Modify any aspect of a browser profile, such as its name, description, viewport + settings, or proxy configuration. Only the fields you provide will be updated; + other fields remain unchanged. + + Args: + + - profile_id: The unique identifier of the browser profile to update + - request: The fields to update (only provided fields will be changed) + + Returns: + + - The updated browser profile with all its current details + + Raises: + + - 404: If the user browser profile doesn't exist Args: extra_headers: Send extra headers @@ -451,7 +593,17 @@ async def list( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> BrowserProfileListResponse: """ - List Browser Profiles + Get a paginated list of all browser profiles for the authenticated user. + + Browser profiles define how your web browsers behave during AI agent tasks, + including settings like viewport size, mobile emulation, proxy configuration, + and ad blocking. Use this endpoint to see all your configured browser profiles. + + Returns: + + - A paginated list of browser profiles + - Total count of profiles + - Page information for navigation Args: extra_headers: Send extra headers @@ -490,9 +642,22 @@ async def delete( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> object: + ) -> None: """ - Delete Browser Profile + Delete a browser profile. + + Permanently removes a browser profile and all its configuration. This action + cannot be undone. The profile will also be removed from the browser service. Any + active sessions using this profile will continue to work, but you won't be able + to create new sessions with the deleted profile. + + Args: + + - profile_id: The unique identifier of the browser profile to delete + + Returns: + + - 204 No Content on successful deletion (idempotent) Args: extra_headers: Send extra headers @@ -505,12 +670,13 @@ async def delete( """ if not profile_id: raise ValueError(f"Expected a non-empty value for `profile_id` but received {profile_id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} return await self._delete( f"/browser-profiles/{profile_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=object, + cast_to=NoneType, ) diff --git a/src/browser_use/resources/sessions/__init__.py b/src/browser_use_sdk/resources/sessions/__init__.py similarity index 100% rename from src/browser_use/resources/sessions/__init__.py rename to src/browser_use_sdk/resources/sessions/__init__.py diff --git a/src/browser_use/resources/sessions/public_share.py b/src/browser_use_sdk/resources/sessions/public_share.py similarity index 74% rename from src/browser_use/resources/sessions/public_share.py rename to src/browser_use_sdk/resources/sessions/public_share.py index f7381d0..8a235d9 100644 --- a/src/browser_use/resources/sessions/public_share.py +++ b/src/browser_use_sdk/resources/sessions/public_share.py @@ -4,7 +4,7 @@ import httpx -from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from ..._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import ( @@ -51,7 +51,29 @@ def create( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> ShareView: """ - Create Session Public Share + Create a public share for a session. + + Generates a public sharing link that allows anyone with the URL to view the + session and its tasks. If a public share already exists for the session, it will + return the existing share instead of creating a new one. + + Public shares are useful for: + + - Sharing results with clients or team members + - Demonstrating AI agent capabilities + - Collaborative review of automated tasks + + Args: + + - session_id: The unique identifier of the agent session to share + + Returns: + + - Public share information including the share URL and usage statistics + + Raises: + + - 404: If the user agent session doesn't exist Args: extra_headers: Send extra headers @@ -84,7 +106,23 @@ def retrieve( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> ShareView: """ - Get Session Public Share + Get information about the public share for a session. + + Retrieves details about the public sharing link for a session, including the + share token, public URL, view count, and last viewed timestamp. This is useful + for monitoring how your shared sessions are being accessed. + + Args: + + - session_id: The unique identifier of the agent session + + Returns: + + - Public share information including the share URL and usage statistics + + Raises: + + - 404: If the user agent session doesn't exist or doesn't have a public share Args: extra_headers: Send extra headers @@ -115,9 +153,25 @@ def delete( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> object: + ) -> None: """ - Delete Session Public Share + Remove the public share for a session. + + Deletes the public sharing link for a session, making it no longer accessible to + anyone with the previous share URL. This is useful for removing access to + sensitive sessions or when you no longer want to share the results. + + Args: + + - session_id: The unique identifier of the agent session + + Returns: + + - 204 No Content on successful deletion (idempotent) + + Raises: + + - 404: If the user agent session doesn't exist Args: extra_headers: Send extra headers @@ -130,12 +184,13 @@ def delete( """ if not session_id: raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} return self._delete( f"/sessions/{session_id}/public-share", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=object, + cast_to=NoneType, ) @@ -171,7 +226,29 @@ async def create( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> ShareView: """ - Create Session Public Share + Create a public share for a session. + + Generates a public sharing link that allows anyone with the URL to view the + session and its tasks. If a public share already exists for the session, it will + return the existing share instead of creating a new one. + + Public shares are useful for: + + - Sharing results with clients or team members + - Demonstrating AI agent capabilities + - Collaborative review of automated tasks + + Args: + + - session_id: The unique identifier of the agent session to share + + Returns: + + - Public share information including the share URL and usage statistics + + Raises: + + - 404: If the user agent session doesn't exist Args: extra_headers: Send extra headers @@ -204,7 +281,23 @@ async def retrieve( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> ShareView: """ - Get Session Public Share + Get information about the public share for a session. + + Retrieves details about the public sharing link for a session, including the + share token, public URL, view count, and last viewed timestamp. This is useful + for monitoring how your shared sessions are being accessed. + + Args: + + - session_id: The unique identifier of the agent session + + Returns: + + - Public share information including the share URL and usage statistics + + Raises: + + - 404: If the user agent session doesn't exist or doesn't have a public share Args: extra_headers: Send extra headers @@ -235,9 +328,25 @@ async def delete( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> object: + ) -> None: """ - Delete Session Public Share + Remove the public share for a session. + + Deletes the public sharing link for a session, making it no longer accessible to + anyone with the previous share URL. This is useful for removing access to + sensitive sessions or when you no longer want to share the results. + + Args: + + - session_id: The unique identifier of the agent session + + Returns: + + - 204 No Content on successful deletion (idempotent) + + Raises: + + - 404: If the user agent session doesn't exist Args: extra_headers: Send extra headers @@ -250,12 +359,13 @@ async def delete( """ if not session_id: raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} return await self._delete( f"/sessions/{session_id}/public-share", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=object, + cast_to=NoneType, ) diff --git a/src/browser_use/resources/sessions/sessions.py b/src/browser_use_sdk/resources/sessions/sessions.py similarity index 62% rename from src/browser_use/resources/sessions/sessions.py rename to src/browser_use_sdk/resources/sessions/sessions.py index 6b6a664..4fc67dd 100644 --- a/src/browser_use/resources/sessions/sessions.py +++ b/src/browser_use_sdk/resources/sessions/sessions.py @@ -7,8 +7,8 @@ import httpx -from ...types import SessionStatus, session_list_params, session_update_params, session_retrieve_params -from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from ...types import SessionStatus, session_list_params, session_update_params +from ..._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource @@ -62,7 +62,6 @@ def retrieve( self, session_id: str, *, - include_tasks: bool | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -71,7 +70,25 @@ def retrieve( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> SessionView: """ - Get Session + Get detailed information about a specific AI agent session. + + Retrieves comprehensive information about a session, including its current + status, live browser URL (if active), recording URL (if completed), and optional + task details. This endpoint is useful for monitoring active sessions or + reviewing completed ones. + + Args: + + - session_id: The unique identifier of the agent session + - params: Optional parameters to control what data is included + + Returns: + + - Complete session information including status, URLs, and optional task details + + Raises: + + - 404: If the user agent session doesn't exist Args: extra_headers: Send extra headers @@ -87,11 +104,7 @@ def retrieve( return self._get( f"/sessions/{session_id}", options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform({"include_tasks": include_tasks}, session_retrieve_params.SessionRetrieveParams), + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=SessionView, ) @@ -109,12 +122,36 @@ def update( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> SessionView: """ - Update Session + Update a session's status or perform actions on it. + + Currently supports stopping a session, which will: + + 1. Stop any running tasks in the session + 2. End the browser session + 3. Generate a recording URL if available + 4. Update the session status to 'stopped' + + This is useful for manually stopping long-running sessions or when you want to + end a session before all tasks are complete. + + Args: + + - session_id: The unique identifier of the agent session to update + - request: The action to perform on the session + + Returns: + + - The updated session information including the new status and recording URL + + Raises: + + - 404: If the user agent session doesn't exist Args: action: Available actions that can be performed on a session - Attributes: STOP: Stop the session and all its associated tasks + Attributes: STOP: Stop the session and all its associated tasks (cannot be + undone) extra_headers: Send extra headers @@ -139,7 +176,6 @@ def list( self, *, filter_by: Optional[SessionStatus] | NotGiven = NOT_GIVEN, - include_tasks: bool | NotGiven = NOT_GIVEN, page_number: int | NotGiven = NOT_GIVEN, page_size: int | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -150,14 +186,27 @@ def list( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> SessionListResponse: """ - List Sessions + Get a paginated list of all AI agent sessions for the authenticated user. + + AI agent sessions represent active or completed browsing sessions where your AI + agents perform tasks. Each session can contain multiple tasks and maintains + browser state throughout the session lifecycle. + + You can filter sessions by status and optionally include task details for each + session. + + Returns: + + - A paginated list of agent sessions + - Total count of sessions + - Page information for navigation + - Optional task details for each session (if requested) Args: filter_by: Enumeration of possible (browser) session states - Attributes: ACTIVE: Session is currently active and running (aka browser is - running) STOPPED: Session has been stopped and is no longer active (aka browser - is stopped) + Attributes: ACTIVE: Session is currently active and running (browser is running) + STOPPED: Session has been stopped and is no longer active (browser is stopped) extra_headers: Send extra headers @@ -177,7 +226,6 @@ def list( query=maybe_transform( { "filter_by": filter_by, - "include_tasks": include_tasks, "page_number": page_number, "page_size": page_size, }, @@ -187,6 +235,52 @@ def list( cast_to=SessionListResponse, ) + def delete( + self, + session_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> None: + """ + Delete a session and all its associated data. + + Permanently removes a session and all its tasks, browser data, and public + shares. This action cannot be undone. Use this endpoint to clean up old sessions + and free up storage space. + + Args: + + - session_id: The unique identifier of the agent session to delete + + Returns: + + - 204 No Content on successful deletion (idempotent) + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not session_id: + raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return self._delete( + f"/sessions/{session_id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + class AsyncSessionsResource(AsyncAPIResource): @cached_property @@ -216,7 +310,6 @@ async def retrieve( self, session_id: str, *, - include_tasks: bool | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -225,7 +318,25 @@ async def retrieve( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> SessionView: """ - Get Session + Get detailed information about a specific AI agent session. + + Retrieves comprehensive information about a session, including its current + status, live browser URL (if active), recording URL (if completed), and optional + task details. This endpoint is useful for monitoring active sessions or + reviewing completed ones. + + Args: + + - session_id: The unique identifier of the agent session + - params: Optional parameters to control what data is included + + Returns: + + - Complete session information including status, URLs, and optional task details + + Raises: + + - 404: If the user agent session doesn't exist Args: extra_headers: Send extra headers @@ -241,13 +352,7 @@ async def retrieve( return await self._get( f"/sessions/{session_id}", options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=await async_maybe_transform( - {"include_tasks": include_tasks}, session_retrieve_params.SessionRetrieveParams - ), + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=SessionView, ) @@ -265,12 +370,36 @@ async def update( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> SessionView: """ - Update Session + Update a session's status or perform actions on it. + + Currently supports stopping a session, which will: + + 1. Stop any running tasks in the session + 2. End the browser session + 3. Generate a recording URL if available + 4. Update the session status to 'stopped' + + This is useful for manually stopping long-running sessions or when you want to + end a session before all tasks are complete. + + Args: + + - session_id: The unique identifier of the agent session to update + - request: The action to perform on the session + + Returns: + + - The updated session information including the new status and recording URL + + Raises: + + - 404: If the user agent session doesn't exist Args: action: Available actions that can be performed on a session - Attributes: STOP: Stop the session and all its associated tasks + Attributes: STOP: Stop the session and all its associated tasks (cannot be + undone) extra_headers: Send extra headers @@ -295,7 +424,6 @@ async def list( self, *, filter_by: Optional[SessionStatus] | NotGiven = NOT_GIVEN, - include_tasks: bool | NotGiven = NOT_GIVEN, page_number: int | NotGiven = NOT_GIVEN, page_size: int | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -306,14 +434,27 @@ async def list( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> SessionListResponse: """ - List Sessions + Get a paginated list of all AI agent sessions for the authenticated user. + + AI agent sessions represent active or completed browsing sessions where your AI + agents perform tasks. Each session can contain multiple tasks and maintains + browser state throughout the session lifecycle. + + You can filter sessions by status and optionally include task details for each + session. + + Returns: + + - A paginated list of agent sessions + - Total count of sessions + - Page information for navigation + - Optional task details for each session (if requested) Args: filter_by: Enumeration of possible (browser) session states - Attributes: ACTIVE: Session is currently active and running (aka browser is - running) STOPPED: Session has been stopped and is no longer active (aka browser - is stopped) + Attributes: ACTIVE: Session is currently active and running (browser is running) + STOPPED: Session has been stopped and is no longer active (browser is stopped) extra_headers: Send extra headers @@ -333,7 +474,6 @@ async def list( query=await async_maybe_transform( { "filter_by": filter_by, - "include_tasks": include_tasks, "page_number": page_number, "page_size": page_size, }, @@ -343,6 +483,52 @@ async def list( cast_to=SessionListResponse, ) + async def delete( + self, + session_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> None: + """ + Delete a session and all its associated data. + + Permanently removes a session and all its tasks, browser data, and public + shares. This action cannot be undone. Use this endpoint to clean up old sessions + and free up storage space. + + Args: + + - session_id: The unique identifier of the agent session to delete + + Returns: + + - 204 No Content on successful deletion (idempotent) + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not session_id: + raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return await self._delete( + f"/sessions/{session_id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + class SessionsResourceWithRawResponse: def __init__(self, sessions: SessionsResource) -> None: @@ -357,6 +543,9 @@ def __init__(self, sessions: SessionsResource) -> None: self.list = to_raw_response_wrapper( sessions.list, ) + self.delete = to_raw_response_wrapper( + sessions.delete, + ) @cached_property def public_share(self) -> PublicShareResourceWithRawResponse: @@ -376,6 +565,9 @@ def __init__(self, sessions: AsyncSessionsResource) -> None: self.list = async_to_raw_response_wrapper( sessions.list, ) + self.delete = async_to_raw_response_wrapper( + sessions.delete, + ) @cached_property def public_share(self) -> AsyncPublicShareResourceWithRawResponse: @@ -395,6 +587,9 @@ def __init__(self, sessions: SessionsResource) -> None: self.list = to_streamed_response_wrapper( sessions.list, ) + self.delete = to_streamed_response_wrapper( + sessions.delete, + ) @cached_property def public_share(self) -> PublicShareResourceWithStreamingResponse: @@ -414,6 +609,9 @@ def __init__(self, sessions: AsyncSessionsResource) -> None: self.list = async_to_streamed_response_wrapper( sessions.list, ) + self.delete = async_to_streamed_response_wrapper( + sessions.delete, + ) @cached_property def public_share(self) -> AsyncPublicShareResourceWithStreamingResponse: diff --git a/src/browser_use/resources/tasks.py b/src/browser_use_sdk/resources/tasks.py similarity index 51% rename from src/browser_use/resources/tasks.py rename to src/browser_use_sdk/resources/tasks.py index de55623..df75c36 100644 --- a/src/browser_use/resources/tasks.py +++ b/src/browser_use_sdk/resources/tasks.py @@ -2,12 +2,13 @@ from __future__ import annotations -from typing import Any, Dict, List, Optional, cast +from typing import Dict, List, Union, Optional +from datetime import datetime from typing_extensions import Literal import httpx -from ..types import task_list_params, task_create_params, task_update_params, task_retrieve_params +from ..types import TaskStatus, task_list_params, task_create_params, task_update_params from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven from .._utils import maybe_transform, async_maybe_transform from .._compat import cached_property @@ -20,10 +21,12 @@ ) from .._base_client import make_request_options from ..types.task_view import TaskView +from ..types.task_status import TaskStatus from ..types.task_list_response import TaskListResponse -from ..types.task_retrieve_response import TaskRetrieveResponse -from ..types.task_retrieve_logs_response import TaskRetrieveLogsResponse -from ..types.task_retrieve_output_file_response import TaskRetrieveOutputFileResponse +from ..types.task_create_response import TaskCreateResponse +from ..types.task_get_logs_response import TaskGetLogsResponse +from ..types.task_get_output_file_response import TaskGetOutputFileResponse +from ..types.task_get_user_uploaded_file_response import TaskGetUserUploadedFileResponse __all__ = ["TasksResource", "AsyncTasksResource"] @@ -64,23 +67,65 @@ def create( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> TaskView: + ) -> TaskCreateResponse: """ - Create Task + Create and start a new AI agent task. + + This is the main endpoint for running AI agents. You can either: + + 1. Start a new session with a new task + 2. Add a follow-up task to an existing session + + When starting a new session: + + - A new browser session is created + - Credits are deducted from your account + - The agent begins executing your task immediately + + When adding to an existing session: + + - The agent continues in the same browser context + - No additional browser start up costs are charged (browser session is already + active) + - The agent can build on previous work + + Key features: + + - Agent profiles: Define agent behavior and capabilities + - Browser profiles: Control browser settings and environment (only used for new + sessions) + - File uploads: Include documents for the agent to work with + - Structured output: Define the format you want results in + - Task metadata: Add custom data for tracking and organization (useful when + using webhooks) + + Args: + + - request: Complete task configuration including agent settings, browser + settings, and task description + + Returns: + + - The created task ID together with the task's session ID + + Raises: + + - 402: If user has insufficient credits for a new session + - 404: If referenced agent/browser profiles don't exist + - 400: If session is stopped or already has a running task Args: - agent_settings: Configuration settings for the AI agent + agent_settings: Configuration settings for the agent - Attributes: llm: The LLM model to use for the agent (default: O3 - best - performance for now) profile_id: ID of the agent profile to use for the task - (None for default) + Attributes: llm: The LLM model to use for the agent start_url: Optional URL to + start the agent on (will not be changed as a step) profile_id: Unique identifier + of the agent profile to use for the task browser_settings: Configuration settings for the browser session - Attributes: session_id: ID of existing session to continue (None for new - session) profile_id: ID of browser profile to use (None for default) - save_browser_data: Whether to save browser state/data for the user to download - later + Attributes: session_id: Unique identifier of existing session to continue + profile_id: Unique identifier of browser profile to use (use if you want to + start a new session) extra_headers: Send extra headers @@ -107,23 +152,45 @@ def create( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=TaskView, + cast_to=TaskCreateResponse, ) def retrieve( self, task_id: str, *, - status_only: bool | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> TaskRetrieveResponse: + ) -> TaskView: """ - Get Task + Get detailed information about a specific AI agent task. + + Retrieves comprehensive information about a task, including its current status, + progress, and detailed execution data. You can choose to get just the status + (for quick polling) or full details including steps and file information. + + Use this endpoint to: + + - Monitor task progress in real-time + - Review completed task results + - Debug failed tasks by examining steps + - Download output files and logs + + Args: + + - task_id: The unique identifier of the agent task + + Returns: + + - Complete task information + + Raises: + + - 404: If the user agent task doesn't exist Args: extra_headers: Send extra headers @@ -136,21 +203,12 @@ def retrieve( """ if not task_id: raise ValueError(f"Expected a non-empty value for `task_id` but received {task_id!r}") - return cast( - TaskRetrieveResponse, - self._get( - f"/tasks/{task_id}", - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform({"status_only": status_only}, task_retrieve_params.TaskRetrieveParams), - ), - cast_to=cast( - Any, TaskRetrieveResponse - ), # Union types cannot be passed in as arguments in the type system + return self._get( + f"/tasks/{task_id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), + cast_to=TaskView, ) def update( @@ -166,7 +224,34 @@ def update( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> TaskView: """ - Update Task + Control the execution of an AI agent task. + + Allows you to pause, resume, or stop tasks, and optionally stop the entire + session. This is useful for: + + - Pausing long-running tasks to review progress + - Stopping tasks that are taking too long + - Ending sessions when you're done with all tasks + + Available actions: + + - STOP: Stop the current task + - PAUSE: Pause the task (can be resumed later) + - RESUME: Resume a paused task + - STOP_TASK_AND_SESSION: Stop the task and end the entire session + + Args: + + - task_id: The unique identifier of the agent task to control + - request: The action to perform on the task + + Returns: + + - The updated task information + + Raises: + + - 404: If the user agent task doesn't exist Args: action: Available actions that can be performed on a task @@ -197,11 +282,12 @@ def update( def list( self, *, - include_output_files: bool | NotGiven = NOT_GIVEN, - include_steps: bool | NotGiven = NOT_GIVEN, - include_user_uploaded_files: bool | NotGiven = NOT_GIVEN, + after: Union[str, datetime, None] | NotGiven = NOT_GIVEN, + before: Union[str, datetime, None] | NotGiven = NOT_GIVEN, + filter_by: Optional[TaskStatus] | NotGiven = NOT_GIVEN, page_number: int | NotGiven = NOT_GIVEN, page_size: int | NotGiven = NOT_GIVEN, + session_id: Optional[str] | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -210,9 +296,27 @@ def list( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> TaskListResponse: """ - List Tasks + Get a paginated list of all Browser Use Agent tasks for the authenticated user. + + Browser Use Agent tasks are the individual jobs that your agents perform within + a session. Each task represents a specific instruction or goal that the agent + works on, such as filling out a form, extracting data, or navigating to specific + pages. + + Returns: + + - A paginated list of Browser Use Agent tasks + - Total count of Browser Use Agent tasks + - Page information for navigation Args: + filter_by: Enumeration of possible task execution states + + Attributes: STARTED: Task has been started and is currently running. PAUSED: + Task execution has been temporarily paused (can be resumed) FINISHED: Task has + finished and the agent has completed the task. STOPPED: Task execution has been + manually stopped (cannot be resumed). + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -230,11 +334,12 @@ def list( timeout=timeout, query=maybe_transform( { - "include_output_files": include_output_files, - "include_steps": include_steps, - "include_user_uploaded_files": include_user_uploaded_files, + "after": after, + "before": before, + "filter_by": filter_by, "page_number": page_number, "page_size": page_size, + "session_id": session_id, }, task_list_params.TaskListParams, ), @@ -242,7 +347,7 @@ def list( cast_to=TaskListResponse, ) - def retrieve_logs( + def get_logs( self, task_id: str, *, @@ -252,9 +357,37 @@ def retrieve_logs( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> TaskRetrieveLogsResponse: + ) -> TaskGetLogsResponse: """ - Get Task Logs + Get a download URL for the execution logs of an AI agent task. + + Task logs contain detailed information about how the AI agent executed the task, + including: + + - Step-by-step reasoning and decisions + - Actions taken on web pages + - Error messages and debugging information + - Performance metrics and timing data + + This is useful for: + + - Understanding how the agent solved the task + - Debugging failed or unexpected results + - Optimizing agent behavior and prompts + - Auditing agent actions for compliance + + Args: + + - task_id: The unique identifier of the agent task + + Returns: + + - A presigned download URL for the task log file + + Raises: + + - 404: If the user agent task doesn't exist + - 500: If the download URL cannot be generated (should not happen) Args: extra_headers: Send extra headers @@ -272,12 +405,12 @@ def retrieve_logs( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=TaskRetrieveLogsResponse, + cast_to=TaskGetLogsResponse, ) - def retrieve_output_file( + def get_output_file( self, - file_name: str, + file_id: str, *, task_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -286,9 +419,33 @@ def retrieve_output_file( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> TaskRetrieveOutputFileResponse: + ) -> TaskGetOutputFileResponse: """ - Get Task Output File + Get a download URL for a specific output file generated by an AI agent task. + + AI agents can generate various output files during task execution, such as: + + - Screenshots of web pages + - Extracted data in CSV/JSON format + - Generated reports or documents + - Downloaded files from websites + + This endpoint provides a secure, time-limited download URL for accessing these + files. The URL expires after a short time for security. + + Args: + + - task_id: The unique identifier of the agent task + - file_id: The unique identifier of the output file + + Returns: + + - A presigned download URL for the requested file + + Raises: + + - 404: If the user agent task or output file doesn't exist + - 500: If the download URL cannot be generated (should not happen) Args: extra_headers: Send extra headers @@ -301,14 +458,71 @@ def retrieve_output_file( """ if not task_id: raise ValueError(f"Expected a non-empty value for `task_id` but received {task_id!r}") - if not file_name: - raise ValueError(f"Expected a non-empty value for `file_name` but received {file_name!r}") + if not file_id: + raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") return self._get( - f"/tasks/{task_id}/output-files/{file_name}", + f"/tasks/{task_id}/output-files/{file_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=TaskRetrieveOutputFileResponse, + cast_to=TaskGetOutputFileResponse, + ) + + def get_user_uploaded_file( + self, + file_id: str, + *, + task_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> TaskGetUserUploadedFileResponse: + """ + Get a download URL for a specific user uploaded file that was used in the task. + + A user can upload files to their account file bucket and reference the name of + the file in a task. These files are then made available for the agent to use + during the agent task run. + + This endpoint provides a secure, time-limited download URL for accessing these + files. The URL expires after a short time for security. + + Args: + + - task_id: The unique identifier of the agent task + - file_id: The unique identifier of the user uploaded file + + Returns: + + - A presigned download URL for the requested file + + Raises: + + - 404: If the user agent task or user uploaded file doesn't exist + - 500: If the download URL cannot be generated (should not happen) + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not task_id: + raise ValueError(f"Expected a non-empty value for `task_id` but received {task_id!r}") + if not file_id: + raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") + return self._get( + f"/tasks/{task_id}/user-uploaded-files/{file_id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=TaskGetUserUploadedFileResponse, ) @@ -348,23 +562,65 @@ async def create( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> TaskView: + ) -> TaskCreateResponse: """ - Create Task + Create and start a new AI agent task. + + This is the main endpoint for running AI agents. You can either: + + 1. Start a new session with a new task + 2. Add a follow-up task to an existing session + + When starting a new session: + + - A new browser session is created + - Credits are deducted from your account + - The agent begins executing your task immediately + + When adding to an existing session: + + - The agent continues in the same browser context + - No additional browser start up costs are charged (browser session is already + active) + - The agent can build on previous work + + Key features: + + - Agent profiles: Define agent behavior and capabilities + - Browser profiles: Control browser settings and environment (only used for new + sessions) + - File uploads: Include documents for the agent to work with + - Structured output: Define the format you want results in + - Task metadata: Add custom data for tracking and organization (useful when + using webhooks) + + Args: + + - request: Complete task configuration including agent settings, browser + settings, and task description + + Returns: + + - The created task ID together with the task's session ID + + Raises: + + - 402: If user has insufficient credits for a new session + - 404: If referenced agent/browser profiles don't exist + - 400: If session is stopped or already has a running task Args: - agent_settings: Configuration settings for the AI agent + agent_settings: Configuration settings for the agent - Attributes: llm: The LLM model to use for the agent (default: O3 - best - performance for now) profile_id: ID of the agent profile to use for the task - (None for default) + Attributes: llm: The LLM model to use for the agent start_url: Optional URL to + start the agent on (will not be changed as a step) profile_id: Unique identifier + of the agent profile to use for the task browser_settings: Configuration settings for the browser session - Attributes: session_id: ID of existing session to continue (None for new - session) profile_id: ID of browser profile to use (None for default) - save_browser_data: Whether to save browser state/data for the user to download - later + Attributes: session_id: Unique identifier of existing session to continue + profile_id: Unique identifier of browser profile to use (use if you want to + start a new session) extra_headers: Send extra headers @@ -391,23 +647,45 @@ async def create( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=TaskView, + cast_to=TaskCreateResponse, ) async def retrieve( self, task_id: str, *, - status_only: bool | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> TaskRetrieveResponse: + ) -> TaskView: """ - Get Task + Get detailed information about a specific AI agent task. + + Retrieves comprehensive information about a task, including its current status, + progress, and detailed execution data. You can choose to get just the status + (for quick polling) or full details including steps and file information. + + Use this endpoint to: + + - Monitor task progress in real-time + - Review completed task results + - Debug failed tasks by examining steps + - Download output files and logs + + Args: + + - task_id: The unique identifier of the agent task + + Returns: + + - Complete task information + + Raises: + + - 404: If the user agent task doesn't exist Args: extra_headers: Send extra headers @@ -420,23 +698,12 @@ async def retrieve( """ if not task_id: raise ValueError(f"Expected a non-empty value for `task_id` but received {task_id!r}") - return cast( - TaskRetrieveResponse, - await self._get( - f"/tasks/{task_id}", - options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=await async_maybe_transform( - {"status_only": status_only}, task_retrieve_params.TaskRetrieveParams - ), - ), - cast_to=cast( - Any, TaskRetrieveResponse - ), # Union types cannot be passed in as arguments in the type system + return await self._get( + f"/tasks/{task_id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), + cast_to=TaskView, ) async def update( @@ -452,7 +719,34 @@ async def update( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> TaskView: """ - Update Task + Control the execution of an AI agent task. + + Allows you to pause, resume, or stop tasks, and optionally stop the entire + session. This is useful for: + + - Pausing long-running tasks to review progress + - Stopping tasks that are taking too long + - Ending sessions when you're done with all tasks + + Available actions: + + - STOP: Stop the current task + - PAUSE: Pause the task (can be resumed later) + - RESUME: Resume a paused task + - STOP_TASK_AND_SESSION: Stop the task and end the entire session + + Args: + + - task_id: The unique identifier of the agent task to control + - request: The action to perform on the task + + Returns: + + - The updated task information + + Raises: + + - 404: If the user agent task doesn't exist Args: action: Available actions that can be performed on a task @@ -483,11 +777,12 @@ async def update( async def list( self, *, - include_output_files: bool | NotGiven = NOT_GIVEN, - include_steps: bool | NotGiven = NOT_GIVEN, - include_user_uploaded_files: bool | NotGiven = NOT_GIVEN, + after: Union[str, datetime, None] | NotGiven = NOT_GIVEN, + before: Union[str, datetime, None] | NotGiven = NOT_GIVEN, + filter_by: Optional[TaskStatus] | NotGiven = NOT_GIVEN, page_number: int | NotGiven = NOT_GIVEN, page_size: int | NotGiven = NOT_GIVEN, + session_id: Optional[str] | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -496,9 +791,27 @@ async def list( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> TaskListResponse: """ - List Tasks + Get a paginated list of all Browser Use Agent tasks for the authenticated user. + + Browser Use Agent tasks are the individual jobs that your agents perform within + a session. Each task represents a specific instruction or goal that the agent + works on, such as filling out a form, extracting data, or navigating to specific + pages. + + Returns: + + - A paginated list of Browser Use Agent tasks + - Total count of Browser Use Agent tasks + - Page information for navigation Args: + filter_by: Enumeration of possible task execution states + + Attributes: STARTED: Task has been started and is currently running. PAUSED: + Task execution has been temporarily paused (can be resumed) FINISHED: Task has + finished and the agent has completed the task. STOPPED: Task execution has been + manually stopped (cannot be resumed). + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -516,11 +829,12 @@ async def list( timeout=timeout, query=await async_maybe_transform( { - "include_output_files": include_output_files, - "include_steps": include_steps, - "include_user_uploaded_files": include_user_uploaded_files, + "after": after, + "before": before, + "filter_by": filter_by, "page_number": page_number, "page_size": page_size, + "session_id": session_id, }, task_list_params.TaskListParams, ), @@ -528,7 +842,7 @@ async def list( cast_to=TaskListResponse, ) - async def retrieve_logs( + async def get_logs( self, task_id: str, *, @@ -538,9 +852,37 @@ async def retrieve_logs( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> TaskRetrieveLogsResponse: + ) -> TaskGetLogsResponse: """ - Get Task Logs + Get a download URL for the execution logs of an AI agent task. + + Task logs contain detailed information about how the AI agent executed the task, + including: + + - Step-by-step reasoning and decisions + - Actions taken on web pages + - Error messages and debugging information + - Performance metrics and timing data + + This is useful for: + + - Understanding how the agent solved the task + - Debugging failed or unexpected results + - Optimizing agent behavior and prompts + - Auditing agent actions for compliance + + Args: + + - task_id: The unique identifier of the agent task + + Returns: + + - A presigned download URL for the task log file + + Raises: + + - 404: If the user agent task doesn't exist + - 500: If the download URL cannot be generated (should not happen) Args: extra_headers: Send extra headers @@ -558,12 +900,12 @@ async def retrieve_logs( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=TaskRetrieveLogsResponse, + cast_to=TaskGetLogsResponse, ) - async def retrieve_output_file( + async def get_output_file( self, - file_name: str, + file_id: str, *, task_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -572,9 +914,33 @@ async def retrieve_output_file( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> TaskRetrieveOutputFileResponse: + ) -> TaskGetOutputFileResponse: """ - Get Task Output File + Get a download URL for a specific output file generated by an AI agent task. + + AI agents can generate various output files during task execution, such as: + + - Screenshots of web pages + - Extracted data in CSV/JSON format + - Generated reports or documents + - Downloaded files from websites + + This endpoint provides a secure, time-limited download URL for accessing these + files. The URL expires after a short time for security. + + Args: + + - task_id: The unique identifier of the agent task + - file_id: The unique identifier of the output file + + Returns: + + - A presigned download URL for the requested file + + Raises: + + - 404: If the user agent task or output file doesn't exist + - 500: If the download URL cannot be generated (should not happen) Args: extra_headers: Send extra headers @@ -587,14 +953,71 @@ async def retrieve_output_file( """ if not task_id: raise ValueError(f"Expected a non-empty value for `task_id` but received {task_id!r}") - if not file_name: - raise ValueError(f"Expected a non-empty value for `file_name` but received {file_name!r}") + if not file_id: + raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") return await self._get( - f"/tasks/{task_id}/output-files/{file_name}", + f"/tasks/{task_id}/output-files/{file_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=TaskRetrieveOutputFileResponse, + cast_to=TaskGetOutputFileResponse, + ) + + async def get_user_uploaded_file( + self, + file_id: str, + *, + task_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> TaskGetUserUploadedFileResponse: + """ + Get a download URL for a specific user uploaded file that was used in the task. + + A user can upload files to their account file bucket and reference the name of + the file in a task. These files are then made available for the agent to use + during the agent task run. + + This endpoint provides a secure, time-limited download URL for accessing these + files. The URL expires after a short time for security. + + Args: + + - task_id: The unique identifier of the agent task + - file_id: The unique identifier of the user uploaded file + + Returns: + + - A presigned download URL for the requested file + + Raises: + + - 404: If the user agent task or user uploaded file doesn't exist + - 500: If the download URL cannot be generated (should not happen) + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not task_id: + raise ValueError(f"Expected a non-empty value for `task_id` but received {task_id!r}") + if not file_id: + raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") + return await self._get( + f"/tasks/{task_id}/user-uploaded-files/{file_id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=TaskGetUserUploadedFileResponse, ) @@ -614,11 +1037,14 @@ def __init__(self, tasks: TasksResource) -> None: self.list = to_raw_response_wrapper( tasks.list, ) - self.retrieve_logs = to_raw_response_wrapper( - tasks.retrieve_logs, + self.get_logs = to_raw_response_wrapper( + tasks.get_logs, + ) + self.get_output_file = to_raw_response_wrapper( + tasks.get_output_file, ) - self.retrieve_output_file = to_raw_response_wrapper( - tasks.retrieve_output_file, + self.get_user_uploaded_file = to_raw_response_wrapper( + tasks.get_user_uploaded_file, ) @@ -638,11 +1064,14 @@ def __init__(self, tasks: AsyncTasksResource) -> None: self.list = async_to_raw_response_wrapper( tasks.list, ) - self.retrieve_logs = async_to_raw_response_wrapper( - tasks.retrieve_logs, + self.get_logs = async_to_raw_response_wrapper( + tasks.get_logs, ) - self.retrieve_output_file = async_to_raw_response_wrapper( - tasks.retrieve_output_file, + self.get_output_file = async_to_raw_response_wrapper( + tasks.get_output_file, + ) + self.get_user_uploaded_file = async_to_raw_response_wrapper( + tasks.get_user_uploaded_file, ) @@ -662,11 +1091,14 @@ def __init__(self, tasks: TasksResource) -> None: self.list = to_streamed_response_wrapper( tasks.list, ) - self.retrieve_logs = to_streamed_response_wrapper( - tasks.retrieve_logs, + self.get_logs = to_streamed_response_wrapper( + tasks.get_logs, + ) + self.get_output_file = to_streamed_response_wrapper( + tasks.get_output_file, ) - self.retrieve_output_file = to_streamed_response_wrapper( - tasks.retrieve_output_file, + self.get_user_uploaded_file = to_streamed_response_wrapper( + tasks.get_user_uploaded_file, ) @@ -686,9 +1118,12 @@ def __init__(self, tasks: AsyncTasksResource) -> None: self.list = async_to_streamed_response_wrapper( tasks.list, ) - self.retrieve_logs = async_to_streamed_response_wrapper( - tasks.retrieve_logs, + self.get_logs = async_to_streamed_response_wrapper( + tasks.get_logs, + ) + self.get_output_file = async_to_streamed_response_wrapper( + tasks.get_output_file, ) - self.retrieve_output_file = async_to_streamed_response_wrapper( - tasks.retrieve_output_file, + self.get_user_uploaded_file = async_to_streamed_response_wrapper( + tasks.get_user_uploaded_file, ) diff --git a/src/browser_use_sdk/resources/users/__init__.py b/src/browser_use_sdk/resources/users/__init__.py new file mode 100644 index 0000000..8b1ed20 --- /dev/null +++ b/src/browser_use_sdk/resources/users/__init__.py @@ -0,0 +1,33 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .me import ( + MeResource, + AsyncMeResource, + MeResourceWithRawResponse, + AsyncMeResourceWithRawResponse, + MeResourceWithStreamingResponse, + AsyncMeResourceWithStreamingResponse, +) +from .users import ( + UsersResource, + AsyncUsersResource, + UsersResourceWithRawResponse, + AsyncUsersResourceWithRawResponse, + UsersResourceWithStreamingResponse, + AsyncUsersResourceWithStreamingResponse, +) + +__all__ = [ + "MeResource", + "AsyncMeResource", + "MeResourceWithRawResponse", + "AsyncMeResourceWithRawResponse", + "MeResourceWithStreamingResponse", + "AsyncMeResourceWithStreamingResponse", + "UsersResource", + "AsyncUsersResource", + "UsersResourceWithRawResponse", + "AsyncUsersResourceWithRawResponse", + "UsersResourceWithStreamingResponse", + "AsyncUsersResourceWithStreamingResponse", +] diff --git a/src/browser_use_sdk/resources/users/me/__init__.py b/src/browser_use_sdk/resources/users/me/__init__.py new file mode 100644 index 0000000..4409f6d --- /dev/null +++ b/src/browser_use_sdk/resources/users/me/__init__.py @@ -0,0 +1,33 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .me import ( + MeResource, + AsyncMeResource, + MeResourceWithRawResponse, + AsyncMeResourceWithRawResponse, + MeResourceWithStreamingResponse, + AsyncMeResourceWithStreamingResponse, +) +from .files import ( + FilesResource, + AsyncFilesResource, + FilesResourceWithRawResponse, + AsyncFilesResourceWithRawResponse, + FilesResourceWithStreamingResponse, + AsyncFilesResourceWithStreamingResponse, +) + +__all__ = [ + "FilesResource", + "AsyncFilesResource", + "FilesResourceWithRawResponse", + "AsyncFilesResourceWithRawResponse", + "FilesResourceWithStreamingResponse", + "AsyncFilesResourceWithStreamingResponse", + "MeResource", + "AsyncMeResource", + "MeResourceWithRawResponse", + "AsyncMeResourceWithRawResponse", + "MeResourceWithStreamingResponse", + "AsyncMeResourceWithStreamingResponse", +] diff --git a/src/browser_use_sdk/resources/users/me/files.py b/src/browser_use_sdk/resources/users/me/files.py new file mode 100644 index 0000000..1468254 --- /dev/null +++ b/src/browser_use_sdk/resources/users/me/files.py @@ -0,0 +1,269 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal + +import httpx + +from ...._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from ...._utils import maybe_transform, async_maybe_transform +from ...._compat import cached_property +from ...._resource import SyncAPIResource, AsyncAPIResource +from ...._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ...._base_client import make_request_options +from ....types.users.me import file_create_presigned_url_params +from ....types.users.me.file_create_presigned_url_response import FileCreatePresignedURLResponse + +__all__ = ["FilesResource", "AsyncFilesResource"] + + +class FilesResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> FilesResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/browser-use/browser-use-python#accessing-raw-response-data-eg-headers + """ + return FilesResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> FilesResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/browser-use/browser-use-python#with_streaming_response + """ + return FilesResourceWithStreamingResponse(self) + + def create_presigned_url( + self, + *, + content_type: Literal[ + "image/jpg", + "image/jpeg", + "image/png", + "image/gif", + "image/webp", + "image/svg+xml", + "application/pdf", + "application/msword", + "application/vnd.openxmlformats-officedocument.wordprocessingml.document", + "application/vnd.ms-excel", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + "text/plain", + "text/csv", + "text/markdown", + ], + file_name: str, + size_bytes: int, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> FileCreatePresignedURLResponse: + """ + Get a presigned URL for uploading files that AI agents can use during tasks. + + This endpoint generates a secure, time-limited upload URL that allows you to + upload files directly to our storage system. These files can then be referenced + in AI agent tasks for the agent to work with. + + Supported use cases: + + - Uploading documents for data extraction tasks + - Providing reference materials for agents + - Sharing files that agents need to process + - Including images or PDFs for analysis + + The upload URL expires after 2 minutes for security. Files are automatically + organized by user ID and can be referenced in task creation using the returned + file name. + + Args: + + - request: File upload details including name, content type, and size + + Returns: + + - Presigned upload URL and form fields for direct file upload + + Raises: + + - 400: If the content type is unsupported + - 500: If the upload URL generation fails (should not happen) + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._post( + "/users/me/files/presigned-url", + body=maybe_transform( + { + "content_type": content_type, + "file_name": file_name, + "size_bytes": size_bytes, + }, + file_create_presigned_url_params.FileCreatePresignedURLParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=FileCreatePresignedURLResponse, + ) + + +class AsyncFilesResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncFilesResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/browser-use/browser-use-python#accessing-raw-response-data-eg-headers + """ + return AsyncFilesResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncFilesResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/browser-use/browser-use-python#with_streaming_response + """ + return AsyncFilesResourceWithStreamingResponse(self) + + async def create_presigned_url( + self, + *, + content_type: Literal[ + "image/jpg", + "image/jpeg", + "image/png", + "image/gif", + "image/webp", + "image/svg+xml", + "application/pdf", + "application/msword", + "application/vnd.openxmlformats-officedocument.wordprocessingml.document", + "application/vnd.ms-excel", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + "text/plain", + "text/csv", + "text/markdown", + ], + file_name: str, + size_bytes: int, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> FileCreatePresignedURLResponse: + """ + Get a presigned URL for uploading files that AI agents can use during tasks. + + This endpoint generates a secure, time-limited upload URL that allows you to + upload files directly to our storage system. These files can then be referenced + in AI agent tasks for the agent to work with. + + Supported use cases: + + - Uploading documents for data extraction tasks + - Providing reference materials for agents + - Sharing files that agents need to process + - Including images or PDFs for analysis + + The upload URL expires after 2 minutes for security. Files are automatically + organized by user ID and can be referenced in task creation using the returned + file name. + + Args: + + - request: File upload details including name, content type, and size + + Returns: + + - Presigned upload URL and form fields for direct file upload + + Raises: + + - 400: If the content type is unsupported + - 500: If the upload URL generation fails (should not happen) + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._post( + "/users/me/files/presigned-url", + body=await async_maybe_transform( + { + "content_type": content_type, + "file_name": file_name, + "size_bytes": size_bytes, + }, + file_create_presigned_url_params.FileCreatePresignedURLParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=FileCreatePresignedURLResponse, + ) + + +class FilesResourceWithRawResponse: + def __init__(self, files: FilesResource) -> None: + self._files = files + + self.create_presigned_url = to_raw_response_wrapper( + files.create_presigned_url, + ) + + +class AsyncFilesResourceWithRawResponse: + def __init__(self, files: AsyncFilesResource) -> None: + self._files = files + + self.create_presigned_url = async_to_raw_response_wrapper( + files.create_presigned_url, + ) + + +class FilesResourceWithStreamingResponse: + def __init__(self, files: FilesResource) -> None: + self._files = files + + self.create_presigned_url = to_streamed_response_wrapper( + files.create_presigned_url, + ) + + +class AsyncFilesResourceWithStreamingResponse: + def __init__(self, files: AsyncFilesResource) -> None: + self._files = files + + self.create_presigned_url = async_to_streamed_response_wrapper( + files.create_presigned_url, + ) diff --git a/src/browser_use_sdk/resources/users/me/me.py b/src/browser_use_sdk/resources/users/me/me.py new file mode 100644 index 0000000..b63585c --- /dev/null +++ b/src/browser_use_sdk/resources/users/me/me.py @@ -0,0 +1,207 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from .files import ( + FilesResource, + AsyncFilesResource, + FilesResourceWithRawResponse, + AsyncFilesResourceWithRawResponse, + FilesResourceWithStreamingResponse, + AsyncFilesResourceWithStreamingResponse, +) +from ...._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from ...._compat import cached_property +from ...._resource import SyncAPIResource, AsyncAPIResource +from ...._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ...._base_client import make_request_options +from ....types.users.me_retrieve_response import MeRetrieveResponse + +__all__ = ["MeResource", "AsyncMeResource"] + + +class MeResource(SyncAPIResource): + @cached_property + def files(self) -> FilesResource: + return FilesResource(self._client) + + @cached_property + def with_raw_response(self) -> MeResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/browser-use/browser-use-python#accessing-raw-response-data-eg-headers + """ + return MeResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> MeResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/browser-use/browser-use-python#with_streaming_response + """ + return MeResourceWithStreamingResponse(self) + + def retrieve( + self, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> MeRetrieveResponse: + """ + Get information about the currently authenticated user. + + Retrieves your user profile information including: + + - Credit balances (monthly and additional credits in USD) + - Account details (email, name, signup date) + + This endpoint is useful for: + + - Checking your remaining credits before running tasks + - Displaying user information in your application + + Returns: + + - Complete user profile information including credits and account details + + Raises: + + - 404: If the user profile cannot be found + """ + return self._get( + "/users/me", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=MeRetrieveResponse, + ) + + +class AsyncMeResource(AsyncAPIResource): + @cached_property + def files(self) -> AsyncFilesResource: + return AsyncFilesResource(self._client) + + @cached_property + def with_raw_response(self) -> AsyncMeResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/browser-use/browser-use-python#accessing-raw-response-data-eg-headers + """ + return AsyncMeResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncMeResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/browser-use/browser-use-python#with_streaming_response + """ + return AsyncMeResourceWithStreamingResponse(self) + + async def retrieve( + self, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> MeRetrieveResponse: + """ + Get information about the currently authenticated user. + + Retrieves your user profile information including: + + - Credit balances (monthly and additional credits in USD) + - Account details (email, name, signup date) + + This endpoint is useful for: + + - Checking your remaining credits before running tasks + - Displaying user information in your application + + Returns: + + - Complete user profile information including credits and account details + + Raises: + + - 404: If the user profile cannot be found + """ + return await self._get( + "/users/me", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=MeRetrieveResponse, + ) + + +class MeResourceWithRawResponse: + def __init__(self, me: MeResource) -> None: + self._me = me + + self.retrieve = to_raw_response_wrapper( + me.retrieve, + ) + + @cached_property + def files(self) -> FilesResourceWithRawResponse: + return FilesResourceWithRawResponse(self._me.files) + + +class AsyncMeResourceWithRawResponse: + def __init__(self, me: AsyncMeResource) -> None: + self._me = me + + self.retrieve = async_to_raw_response_wrapper( + me.retrieve, + ) + + @cached_property + def files(self) -> AsyncFilesResourceWithRawResponse: + return AsyncFilesResourceWithRawResponse(self._me.files) + + +class MeResourceWithStreamingResponse: + def __init__(self, me: MeResource) -> None: + self._me = me + + self.retrieve = to_streamed_response_wrapper( + me.retrieve, + ) + + @cached_property + def files(self) -> FilesResourceWithStreamingResponse: + return FilesResourceWithStreamingResponse(self._me.files) + + +class AsyncMeResourceWithStreamingResponse: + def __init__(self, me: AsyncMeResource) -> None: + self._me = me + + self.retrieve = async_to_streamed_response_wrapper( + me.retrieve, + ) + + @cached_property + def files(self) -> AsyncFilesResourceWithStreamingResponse: + return AsyncFilesResourceWithStreamingResponse(self._me.files) diff --git a/src/browser_use_sdk/resources/users/users.py b/src/browser_use_sdk/resources/users/users.py new file mode 100644 index 0000000..95dfc93 --- /dev/null +++ b/src/browser_use_sdk/resources/users/users.py @@ -0,0 +1,102 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from .me.me import ( + MeResource, + AsyncMeResource, + MeResourceWithRawResponse, + AsyncMeResourceWithRawResponse, + MeResourceWithStreamingResponse, + AsyncMeResourceWithStreamingResponse, +) +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource + +__all__ = ["UsersResource", "AsyncUsersResource"] + + +class UsersResource(SyncAPIResource): + @cached_property + def me(self) -> MeResource: + return MeResource(self._client) + + @cached_property + def with_raw_response(self) -> UsersResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/browser-use/browser-use-python#accessing-raw-response-data-eg-headers + """ + return UsersResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> UsersResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/browser-use/browser-use-python#with_streaming_response + """ + return UsersResourceWithStreamingResponse(self) + + +class AsyncUsersResource(AsyncAPIResource): + @cached_property + def me(self) -> AsyncMeResource: + return AsyncMeResource(self._client) + + @cached_property + def with_raw_response(self) -> AsyncUsersResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/browser-use/browser-use-python#accessing-raw-response-data-eg-headers + """ + return AsyncUsersResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncUsersResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/browser-use/browser-use-python#with_streaming_response + """ + return AsyncUsersResourceWithStreamingResponse(self) + + +class UsersResourceWithRawResponse: + def __init__(self, users: UsersResource) -> None: + self._users = users + + @cached_property + def me(self) -> MeResourceWithRawResponse: + return MeResourceWithRawResponse(self._users.me) + + +class AsyncUsersResourceWithRawResponse: + def __init__(self, users: AsyncUsersResource) -> None: + self._users = users + + @cached_property + def me(self) -> AsyncMeResourceWithRawResponse: + return AsyncMeResourceWithRawResponse(self._users.me) + + +class UsersResourceWithStreamingResponse: + def __init__(self, users: UsersResource) -> None: + self._users = users + + @cached_property + def me(self) -> MeResourceWithStreamingResponse: + return MeResourceWithStreamingResponse(self._users.me) + + +class AsyncUsersResourceWithStreamingResponse: + def __init__(self, users: AsyncUsersResource) -> None: + self._users = users + + @cached_property + def me(self) -> AsyncMeResourceWithStreamingResponse: + return AsyncMeResourceWithStreamingResponse(self._users.me) diff --git a/src/browser_use/types/__init__.py b/src/browser_use_sdk/types/__init__.py similarity index 77% rename from src/browser_use/types/__init__.py rename to src/browser_use_sdk/types/__init__.py index b2eac92..105b042 100644 --- a/src/browser_use/types/__init__.py +++ b/src/browser_use_sdk/types/__init__.py @@ -2,11 +2,14 @@ from __future__ import annotations +from .file_view import FileView as FileView from .llm_model import LlmModel as LlmModel from .task_view import TaskView as TaskView from .task_status import TaskStatus as TaskStatus from .session_view import SessionView as SessionView from .session_status import SessionStatus as SessionStatus +from .task_item_view import TaskItemView as TaskItemView +from .task_step_view import TaskStepView as TaskStepView from .task_list_params import TaskListParams as TaskListParams from .agent_profile_view import AgentProfileView as AgentProfileView from .proxy_country_code import ProxyCountryCode as ProxyCountryCode @@ -15,18 +18,17 @@ from .task_update_params import TaskUpdateParams as TaskUpdateParams from .session_list_params import SessionListParams as SessionListParams from .browser_profile_view import BrowserProfileView as BrowserProfileView -from .task_retrieve_params import TaskRetrieveParams as TaskRetrieveParams +from .task_create_response import TaskCreateResponse as TaskCreateResponse from .session_list_response import SessionListResponse as SessionListResponse from .session_update_params import SessionUpdateParams as SessionUpdateParams -from .task_retrieve_response import TaskRetrieveResponse as TaskRetrieveResponse -from .session_retrieve_params import SessionRetrieveParams as SessionRetrieveParams +from .task_get_logs_response import TaskGetLogsResponse as TaskGetLogsResponse from .agent_profile_list_params import AgentProfileListParams as AgentProfileListParams from .agent_profile_create_params import AgentProfileCreateParams as AgentProfileCreateParams from .agent_profile_list_response import AgentProfileListResponse as AgentProfileListResponse from .agent_profile_update_params import AgentProfileUpdateParams as AgentProfileUpdateParams from .browser_profile_list_params import BrowserProfileListParams as BrowserProfileListParams -from .task_retrieve_logs_response import TaskRetrieveLogsResponse as TaskRetrieveLogsResponse from .browser_profile_create_params import BrowserProfileCreateParams as BrowserProfileCreateParams from .browser_profile_list_response import BrowserProfileListResponse as BrowserProfileListResponse from .browser_profile_update_params import BrowserProfileUpdateParams as BrowserProfileUpdateParams -from .task_retrieve_output_file_response import TaskRetrieveOutputFileResponse as TaskRetrieveOutputFileResponse +from .task_get_output_file_response import TaskGetOutputFileResponse as TaskGetOutputFileResponse +from .task_get_user_uploaded_file_response import TaskGetUserUploadedFileResponse as TaskGetUserUploadedFileResponse diff --git a/src/browser_use/types/agent_profile_create_params.py b/src/browser_use_sdk/types/agent_profile_create_params.py similarity index 87% rename from src/browser_use/types/agent_profile_create_params.py rename to src/browser_use_sdk/types/agent_profile_create_params.py index a1adf02..ef3080b 100644 --- a/src/browser_use/types/agent_profile_create_params.py +++ b/src/browser_use_sdk/types/agent_profile_create_params.py @@ -15,6 +15,8 @@ class AgentProfileCreateParams(TypedDict, total=False): allowed_domains: Annotated[List[str], PropertyInfo(alias="allowedDomains")] + custom_system_prompt_extension: Annotated[str, PropertyInfo(alias="customSystemPromptExtension")] + description: str flash_mode: Annotated[bool, PropertyInfo(alias="flashMode")] @@ -23,8 +25,6 @@ class AgentProfileCreateParams(TypedDict, total=False): max_agent_steps: Annotated[int, PropertyInfo(alias="maxAgentSteps")] - system_prompt: Annotated[str, PropertyInfo(alias="systemPrompt")] - thinking: bool vision: bool diff --git a/src/browser_use/types/agent_profile_list_params.py b/src/browser_use_sdk/types/agent_profile_list_params.py similarity index 100% rename from src/browser_use/types/agent_profile_list_params.py rename to src/browser_use_sdk/types/agent_profile_list_params.py diff --git a/src/browser_use/types/agent_profile_list_response.py b/src/browser_use_sdk/types/agent_profile_list_response.py similarity index 100% rename from src/browser_use/types/agent_profile_list_response.py rename to src/browser_use_sdk/types/agent_profile_list_response.py diff --git a/src/browser_use/types/agent_profile_update_params.py b/src/browser_use_sdk/types/agent_profile_update_params.py similarity index 87% rename from src/browser_use/types/agent_profile_update_params.py rename to src/browser_use_sdk/types/agent_profile_update_params.py index 850ade8..8595815 100644 --- a/src/browser_use/types/agent_profile_update_params.py +++ b/src/browser_use_sdk/types/agent_profile_update_params.py @@ -13,6 +13,8 @@ class AgentProfileUpdateParams(TypedDict, total=False): allowed_domains: Annotated[Optional[List[str]], PropertyInfo(alias="allowedDomains")] + custom_system_prompt_extension: Annotated[Optional[str], PropertyInfo(alias="customSystemPromptExtension")] + description: Optional[str] flash_mode: Annotated[Optional[bool], PropertyInfo(alias="flashMode")] @@ -23,8 +25,6 @@ class AgentProfileUpdateParams(TypedDict, total=False): name: Optional[str] - system_prompt: Annotated[Optional[str], PropertyInfo(alias="systemPrompt")] - thinking: Optional[bool] vision: Optional[bool] diff --git a/src/browser_use/types/agent_profile_view.py b/src/browser_use_sdk/types/agent_profile_view.py similarity index 89% rename from src/browser_use/types/agent_profile_view.py rename to src/browser_use_sdk/types/agent_profile_view.py index bd98d00..1c10f12 100644 --- a/src/browser_use/types/agent_profile_view.py +++ b/src/browser_use_sdk/types/agent_profile_view.py @@ -17,6 +17,8 @@ class AgentProfileView(BaseModel): created_at: datetime = FieldInfo(alias="createdAt") + custom_system_prompt_extension: str = FieldInfo(alias="customSystemPromptExtension") + description: str flash_mode: bool = FieldInfo(alias="flashMode") @@ -27,8 +29,6 @@ class AgentProfileView(BaseModel): name: str - system_prompt: str = FieldInfo(alias="systemPrompt") - thinking: bool updated_at: datetime = FieldInfo(alias="updatedAt") diff --git a/src/browser_use/types/browser_profile_create_params.py b/src/browser_use_sdk/types/browser_profile_create_params.py similarity index 100% rename from src/browser_use/types/browser_profile_create_params.py rename to src/browser_use_sdk/types/browser_profile_create_params.py diff --git a/src/browser_use/types/browser_profile_list_params.py b/src/browser_use_sdk/types/browser_profile_list_params.py similarity index 100% rename from src/browser_use/types/browser_profile_list_params.py rename to src/browser_use_sdk/types/browser_profile_list_params.py diff --git a/src/browser_use/types/browser_profile_list_response.py b/src/browser_use_sdk/types/browser_profile_list_response.py similarity index 100% rename from src/browser_use/types/browser_profile_list_response.py rename to src/browser_use_sdk/types/browser_profile_list_response.py diff --git a/src/browser_use/types/browser_profile_update_params.py b/src/browser_use_sdk/types/browser_profile_update_params.py similarity index 100% rename from src/browser_use/types/browser_profile_update_params.py rename to src/browser_use_sdk/types/browser_profile_update_params.py diff --git a/src/browser_use/types/browser_profile_view.py b/src/browser_use_sdk/types/browser_profile_view.py similarity index 100% rename from src/browser_use/types/browser_profile_view.py rename to src/browser_use_sdk/types/browser_profile_view.py diff --git a/src/browser_use_sdk/types/file_view.py b/src/browser_use_sdk/types/file_view.py new file mode 100644 index 0000000..620c57c --- /dev/null +++ b/src/browser_use_sdk/types/file_view.py @@ -0,0 +1,13 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = ["FileView"] + + +class FileView(BaseModel): + id: str + + file_name: str = FieldInfo(alias="fileName") diff --git a/src/browser_use/types/llm_model.py b/src/browser_use_sdk/types/llm_model.py similarity index 100% rename from src/browser_use/types/llm_model.py rename to src/browser_use_sdk/types/llm_model.py diff --git a/src/browser_use/types/proxy_country_code.py b/src/browser_use_sdk/types/proxy_country_code.py similarity index 100% rename from src/browser_use/types/proxy_country_code.py rename to src/browser_use_sdk/types/proxy_country_code.py diff --git a/src/browser_use/types/session_list_params.py b/src/browser_use_sdk/types/session_list_params.py similarity index 78% rename from src/browser_use/types/session_list_params.py rename to src/browser_use_sdk/types/session_list_params.py index 2de4f0d..0bd7b72 100644 --- a/src/browser_use/types/session_list_params.py +++ b/src/browser_use_sdk/types/session_list_params.py @@ -15,13 +15,10 @@ class SessionListParams(TypedDict, total=False): filter_by: Annotated[Optional[SessionStatus], PropertyInfo(alias="filterBy")] """Enumeration of possible (browser) session states - Attributes: ACTIVE: Session is currently active and running (aka browser is - running) STOPPED: Session has been stopped and is no longer active (aka browser - is stopped) + Attributes: ACTIVE: Session is currently active and running (browser is running) + STOPPED: Session has been stopped and is no longer active (browser is stopped) """ - include_tasks: Annotated[bool, PropertyInfo(alias="includeTasks")] - page_number: Annotated[int, PropertyInfo(alias="pageNumber")] page_size: Annotated[int, PropertyInfo(alias="pageSize")] diff --git a/src/browser_use_sdk/types/session_list_response.py b/src/browser_use_sdk/types/session_list_response.py new file mode 100644 index 0000000..0958cfa --- /dev/null +++ b/src/browser_use_sdk/types/session_list_response.py @@ -0,0 +1,38 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from datetime import datetime + +from pydantic import Field as FieldInfo + +from .._models import BaseModel +from .session_status import SessionStatus + +__all__ = ["SessionListResponse", "Item"] + + +class Item(BaseModel): + id: str + + started_at: datetime = FieldInfo(alias="startedAt") + + status: SessionStatus + """Enumeration of possible (browser) session states + + Attributes: ACTIVE: Session is currently active and running (browser is running) + STOPPED: Session has been stopped and is no longer active (browser is stopped) + """ + + finished_at: Optional[datetime] = FieldInfo(alias="finishedAt", default=None) + + live_url: Optional[str] = FieldInfo(alias="liveUrl", default=None) + + +class SessionListResponse(BaseModel): + items: List[Item] + + page_number: int = FieldInfo(alias="pageNumber") + + page_size: int = FieldInfo(alias="pageSize") + + total_items: int = FieldInfo(alias="totalItems") diff --git a/src/browser_use/types/session_status.py b/src/browser_use_sdk/types/session_status.py similarity index 100% rename from src/browser_use/types/session_status.py rename to src/browser_use_sdk/types/session_status.py diff --git a/src/browser_use/types/session_update_params.py b/src/browser_use_sdk/types/session_update_params.py similarity index 94% rename from src/browser_use/types/session_update_params.py rename to src/browser_use_sdk/types/session_update_params.py index f722648..92734a7 100644 --- a/src/browser_use/types/session_update_params.py +++ b/src/browser_use_sdk/types/session_update_params.py @@ -11,5 +11,6 @@ class SessionUpdateParams(TypedDict, total=False): action: Required[Literal["stop"]] """Available actions that can be performed on a session - Attributes: STOP: Stop the session and all its associated tasks + Attributes: STOP: Stop the session and all its associated tasks (cannot be + undone) """ diff --git a/src/browser_use/types/session_view.py b/src/browser_use_sdk/types/session_view.py similarity index 81% rename from src/browser_use/types/session_view.py rename to src/browser_use_sdk/types/session_view.py index 0ad8e00..492e4aa 100644 --- a/src/browser_use/types/session_view.py +++ b/src/browser_use_sdk/types/session_view.py @@ -6,8 +6,8 @@ from pydantic import Field as FieldInfo from .._models import BaseModel -from .task_view import TaskView from .session_status import SessionStatus +from .task_item_view import TaskItemView __all__ = ["SessionView"] @@ -20,9 +20,8 @@ class SessionView(BaseModel): status: SessionStatus """Enumeration of possible (browser) session states - Attributes: ACTIVE: Session is currently active and running (aka browser is - running) STOPPED: Session has been stopped and is no longer active (aka browser - is stopped) + Attributes: ACTIVE: Session is currently active and running (browser is running) + STOPPED: Session has been stopped and is no longer active (browser is stopped) """ finished_at: Optional[datetime] = FieldInfo(alias="finishedAt", default=None) @@ -33,4 +32,4 @@ class SessionView(BaseModel): record_url: Optional[str] = FieldInfo(alias="recordUrl", default=None) - tasks: Optional[List[TaskView]] = None + tasks: Optional[List[TaskItemView]] = None diff --git a/src/browser_use/types/sessions/__init__.py b/src/browser_use_sdk/types/sessions/__init__.py similarity index 100% rename from src/browser_use/types/sessions/__init__.py rename to src/browser_use_sdk/types/sessions/__init__.py diff --git a/src/browser_use/types/sessions/share_view.py b/src/browser_use_sdk/types/sessions/share_view.py similarity index 100% rename from src/browser_use/types/sessions/share_view.py rename to src/browser_use_sdk/types/sessions/share_view.py diff --git a/src/browser_use/types/task_create_params.py b/src/browser_use_sdk/types/task_create_params.py similarity index 70% rename from src/browser_use/types/task_create_params.py rename to src/browser_use_sdk/types/task_create_params.py index 5773e37..7943846 100644 --- a/src/browser_use/types/task_create_params.py +++ b/src/browser_use_sdk/types/task_create_params.py @@ -15,20 +15,19 @@ class TaskCreateParams(TypedDict, total=False): task: Required[str] agent_settings: Annotated[AgentSettings, PropertyInfo(alias="agentSettings")] - """Configuration settings for the AI agent + """Configuration settings for the agent - Attributes: llm: The LLM model to use for the agent (default: O3 - best - performance for now) profile_id: ID of the agent profile to use for the task - (None for default) + Attributes: llm: The LLM model to use for the agent start_url: Optional URL to + start the agent on (will not be changed as a step) profile_id: Unique identifier + of the agent profile to use for the task """ browser_settings: Annotated[BrowserSettings, PropertyInfo(alias="browserSettings")] """Configuration settings for the browser session - Attributes: session_id: ID of existing session to continue (None for new - session) profile_id: ID of browser profile to use (None for default) - save_browser_data: Whether to save browser state/data for the user to download - later + Attributes: session_id: Unique identifier of existing session to continue + profile_id: Unique identifier of browser profile to use (use if you want to + start a new session) """ included_file_names: Annotated[Optional[List[str]], PropertyInfo(alias="includedFileNames")] @@ -45,10 +44,10 @@ class AgentSettings(TypedDict, total=False): profile_id: Annotated[Optional[str], PropertyInfo(alias="profileId")] + start_url: Annotated[Optional[str], PropertyInfo(alias="startUrl")] + class BrowserSettings(TypedDict, total=False): profile_id: Annotated[Optional[str], PropertyInfo(alias="profileId")] - save_browser_data: Annotated[bool, PropertyInfo(alias="saveBrowserData")] - session_id: Annotated[Optional[str], PropertyInfo(alias="sessionId")] diff --git a/src/browser_use_sdk/types/task_create_response.py b/src/browser_use_sdk/types/task_create_response.py new file mode 100644 index 0000000..b17ab00 --- /dev/null +++ b/src/browser_use_sdk/types/task_create_response.py @@ -0,0 +1,13 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = ["TaskCreateResponse"] + + +class TaskCreateResponse(BaseModel): + id: str + + session_id: str = FieldInfo(alias="sessionId") diff --git a/src/browser_use/types/task_retrieve_logs_response.py b/src/browser_use_sdk/types/task_get_logs_response.py similarity index 72% rename from src/browser_use/types/task_retrieve_logs_response.py rename to src/browser_use_sdk/types/task_get_logs_response.py index cdee450..5bc035c 100644 --- a/src/browser_use/types/task_retrieve_logs_response.py +++ b/src/browser_use_sdk/types/task_get_logs_response.py @@ -4,8 +4,8 @@ from .._models import BaseModel -__all__ = ["TaskRetrieveLogsResponse"] +__all__ = ["TaskGetLogsResponse"] -class TaskRetrieveLogsResponse(BaseModel): +class TaskGetLogsResponse(BaseModel): download_url: str = FieldInfo(alias="downloadUrl") diff --git a/src/browser_use/types/task_retrieve_output_file_response.py b/src/browser_use_sdk/types/task_get_output_file_response.py similarity index 59% rename from src/browser_use/types/task_retrieve_output_file_response.py rename to src/browser_use_sdk/types/task_get_output_file_response.py index d532e3d..812ac90 100644 --- a/src/browser_use/types/task_retrieve_output_file_response.py +++ b/src/browser_use_sdk/types/task_get_output_file_response.py @@ -4,8 +4,12 @@ from .._models import BaseModel -__all__ = ["TaskRetrieveOutputFileResponse"] +__all__ = ["TaskGetOutputFileResponse"] -class TaskRetrieveOutputFileResponse(BaseModel): +class TaskGetOutputFileResponse(BaseModel): + id: str + download_url: str = FieldInfo(alias="downloadUrl") + + file_name: str = FieldInfo(alias="fileName") diff --git a/src/browser_use_sdk/types/task_get_user_uploaded_file_response.py b/src/browser_use_sdk/types/task_get_user_uploaded_file_response.py new file mode 100644 index 0000000..f802207 --- /dev/null +++ b/src/browser_use_sdk/types/task_get_user_uploaded_file_response.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = ["TaskGetUserUploadedFileResponse"] + + +class TaskGetUserUploadedFileResponse(BaseModel): + id: str + + download_url: str = FieldInfo(alias="downloadUrl") + + file_name: str = FieldInfo(alias="fileName") diff --git a/src/browser_use_sdk/types/task_item_view.py b/src/browser_use_sdk/types/task_item_view.py new file mode 100644 index 0000000..ff7c731 --- /dev/null +++ b/src/browser_use_sdk/types/task_item_view.py @@ -0,0 +1,45 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Dict, Optional +from datetime import datetime + +from pydantic import Field as FieldInfo + +from .._models import BaseModel +from .llm_model import LlmModel +from .task_status import TaskStatus + +__all__ = ["TaskItemView"] + + +class TaskItemView(BaseModel): + id: str + + is_scheduled: bool = FieldInfo(alias="isScheduled") + + llm: LlmModel + + session_id: str = FieldInfo(alias="sessionId") + + started_at: datetime = FieldInfo(alias="startedAt") + + status: TaskStatus + """Enumeration of possible task execution states + + Attributes: STARTED: Task has been started and is currently running. PAUSED: + Task execution has been temporarily paused (can be resumed) FINISHED: Task has + finished and the agent has completed the task. STOPPED: Task execution has been + manually stopped (cannot be resumed). + """ + + task: str + + browser_use_version: Optional[str] = FieldInfo(alias="browserUseVersion", default=None) + + done_output: Optional[str] = FieldInfo(alias="doneOutput", default=None) + + finished_at: Optional[datetime] = FieldInfo(alias="finishedAt", default=None) + + is_success: Optional[bool] = FieldInfo(alias="isSuccess", default=None) + + metadata: Optional[Dict[str, object]] = None diff --git a/src/browser_use_sdk/types/task_list_params.py b/src/browser_use_sdk/types/task_list_params.py new file mode 100644 index 0000000..0d83aaa --- /dev/null +++ b/src/browser_use_sdk/types/task_list_params.py @@ -0,0 +1,33 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Union, Optional +from datetime import datetime +from typing_extensions import Annotated, TypedDict + +from .._utils import PropertyInfo +from .task_status import TaskStatus + +__all__ = ["TaskListParams"] + + +class TaskListParams(TypedDict, total=False): + after: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")] + + before: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")] + + filter_by: Annotated[Optional[TaskStatus], PropertyInfo(alias="filterBy")] + """Enumeration of possible task execution states + + Attributes: STARTED: Task has been started and is currently running. PAUSED: + Task execution has been temporarily paused (can be resumed) FINISHED: Task has + finished and the agent has completed the task. STOPPED: Task execution has been + manually stopped (cannot be resumed). + """ + + page_number: Annotated[int, PropertyInfo(alias="pageNumber")] + + page_size: Annotated[int, PropertyInfo(alias="pageSize")] + + session_id: Annotated[Optional[str], PropertyInfo(alias="sessionId")] diff --git a/src/browser_use/types/task_list_response.py b/src/browser_use_sdk/types/task_list_response.py similarity index 85% rename from src/browser_use/types/task_list_response.py rename to src/browser_use_sdk/types/task_list_response.py index 6237338..de14f6e 100644 --- a/src/browser_use/types/task_list_response.py +++ b/src/browser_use_sdk/types/task_list_response.py @@ -5,13 +5,13 @@ from pydantic import Field as FieldInfo from .._models import BaseModel -from .task_view import TaskView +from .task_item_view import TaskItemView __all__ = ["TaskListResponse"] class TaskListResponse(BaseModel): - items: List[TaskView] + items: List[TaskItemView] page_number: int = FieldInfo(alias="pageNumber") diff --git a/src/browser_use/types/task_status.py b/src/browser_use_sdk/types/task_status.py similarity index 68% rename from src/browser_use/types/task_status.py rename to src/browser_use_sdk/types/task_status.py index e0bc452..0eabe70 100644 --- a/src/browser_use/types/task_status.py +++ b/src/browser_use_sdk/types/task_status.py @@ -4,4 +4,4 @@ __all__ = ["TaskStatus"] -TaskStatus: TypeAlias = Literal["started", "paused", "stopped", "finished"] +TaskStatus: TypeAlias = Literal["started", "paused", "finished", "stopped"] diff --git a/src/browser_use_sdk/types/task_step_view.py b/src/browser_use_sdk/types/task_step_view.py new file mode 100644 index 0000000..b32e08c --- /dev/null +++ b/src/browser_use_sdk/types/task_step_view.py @@ -0,0 +1,25 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = ["TaskStepView"] + + +class TaskStepView(BaseModel): + actions: List[str] + + evaluation_previous_goal: str = FieldInfo(alias="evaluationPreviousGoal") + + memory: str + + next_goal: str = FieldInfo(alias="nextGoal") + + number: int + + url: str + + screenshot_url: Optional[str] = FieldInfo(alias="screenshotUrl", default=None) diff --git a/src/browser_use/types/task_update_params.py b/src/browser_use_sdk/types/task_update_params.py similarity index 100% rename from src/browser_use/types/task_update_params.py rename to src/browser_use_sdk/types/task_update_params.py diff --git a/src/browser_use_sdk/types/task_view.py b/src/browser_use_sdk/types/task_view.py new file mode 100644 index 0000000..2bc4812 --- /dev/null +++ b/src/browser_use_sdk/types/task_view.py @@ -0,0 +1,80 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Dict, List, Optional +from datetime import datetime +from typing_extensions import Literal + +from pydantic import Field as FieldInfo + +from .._models import BaseModel +from .file_view import FileView +from .llm_model import LlmModel +from .task_status import TaskStatus +from .task_step_view import TaskStepView + +__all__ = ["TaskView", "Session"] + + +class Session(BaseModel): + id: str + + started_at: datetime = FieldInfo(alias="startedAt") + + status: Literal["active", "stopped"] + """Enumeration of possible (browser) session states + + Attributes: ACTIVE: Session is currently active and running (browser is running) + STOPPED: Session has been stopped and is no longer active (browser is stopped) + """ + + finished_at: Optional[datetime] = FieldInfo(alias="finishedAt", default=None) + + live_url: Optional[str] = FieldInfo(alias="liveUrl", default=None) + + +class TaskView(BaseModel): + id: str + + is_scheduled: bool = FieldInfo(alias="isScheduled") + + llm: LlmModel + + output_files: List[FileView] = FieldInfo(alias="outputFiles") + + session: Session + """View model for representing a session that a task belongs to + + Attributes: id: Unique identifier for the session status: Current status of the + session (active/stopped) live_url: URL where the browser can be viewed live in + real-time. started_at: Timestamp when the session was created and started. + finished_at: Timestamp when the session was stopped (None if still active). + """ + + session_id: str = FieldInfo(alias="sessionId") + + started_at: datetime = FieldInfo(alias="startedAt") + + status: TaskStatus + """Enumeration of possible task execution states + + Attributes: STARTED: Task has been started and is currently running. PAUSED: + Task execution has been temporarily paused (can be resumed) FINISHED: Task has + finished and the agent has completed the task. STOPPED: Task execution has been + manually stopped (cannot be resumed). + """ + + steps: List[TaskStepView] + + task: str + + user_uploaded_files: List[FileView] = FieldInfo(alias="userUploadedFiles") + + browser_use_version: Optional[str] = FieldInfo(alias="browserUseVersion", default=None) + + done_output: Optional[str] = FieldInfo(alias="doneOutput", default=None) + + finished_at: Optional[datetime] = FieldInfo(alias="finishedAt", default=None) + + is_success: Optional[bool] = FieldInfo(alias="isSuccess", default=None) + + metadata: Optional[Dict[str, object]] = None diff --git a/src/browser_use_sdk/types/users/__init__.py b/src/browser_use_sdk/types/users/__init__.py new file mode 100644 index 0000000..de5007b --- /dev/null +++ b/src/browser_use_sdk/types/users/__init__.py @@ -0,0 +1,5 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from .me_retrieve_response import MeRetrieveResponse as MeRetrieveResponse diff --git a/src/browser_use_sdk/types/users/me/__init__.py b/src/browser_use_sdk/types/users/me/__init__.py new file mode 100644 index 0000000..27f2334 --- /dev/null +++ b/src/browser_use_sdk/types/users/me/__init__.py @@ -0,0 +1,6 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from .file_create_presigned_url_params import FileCreatePresignedURLParams as FileCreatePresignedURLParams +from .file_create_presigned_url_response import FileCreatePresignedURLResponse as FileCreatePresignedURLResponse diff --git a/src/browser_use_sdk/types/users/me/file_create_presigned_url_params.py b/src/browser_use_sdk/types/users/me/file_create_presigned_url_params.py new file mode 100644 index 0000000..368b0c9 --- /dev/null +++ b/src/browser_use_sdk/types/users/me/file_create_presigned_url_params.py @@ -0,0 +1,37 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, Required, Annotated, TypedDict + +from ...._utils import PropertyInfo + +__all__ = ["FileCreatePresignedURLParams"] + + +class FileCreatePresignedURLParams(TypedDict, total=False): + content_type: Required[ + Annotated[ + Literal[ + "image/jpg", + "image/jpeg", + "image/png", + "image/gif", + "image/webp", + "image/svg+xml", + "application/pdf", + "application/msword", + "application/vnd.openxmlformats-officedocument.wordprocessingml.document", + "application/vnd.ms-excel", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + "text/plain", + "text/csv", + "text/markdown", + ], + PropertyInfo(alias="contentType"), + ] + ] + + file_name: Required[Annotated[str, PropertyInfo(alias="fileName")]] + + size_bytes: Required[Annotated[int, PropertyInfo(alias="sizeBytes")]] diff --git a/src/browser_use_sdk/types/users/me/file_create_presigned_url_response.py b/src/browser_use_sdk/types/users/me/file_create_presigned_url_response.py new file mode 100644 index 0000000..f3dc32f --- /dev/null +++ b/src/browser_use_sdk/types/users/me/file_create_presigned_url_response.py @@ -0,0 +1,22 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Dict +from typing_extensions import Literal + +from pydantic import Field as FieldInfo + +from ...._models import BaseModel + +__all__ = ["FileCreatePresignedURLResponse"] + + +class FileCreatePresignedURLResponse(BaseModel): + expires_in: int = FieldInfo(alias="expiresIn") + + fields: Dict[str, str] + + file_name: str = FieldInfo(alias="fileName") + + method: Literal["POST"] + + url: str diff --git a/src/browser_use_sdk/types/users/me_retrieve_response.py b/src/browser_use_sdk/types/users/me_retrieve_response.py new file mode 100644 index 0000000..75d83b0 --- /dev/null +++ b/src/browser_use_sdk/types/users/me_retrieve_response.py @@ -0,0 +1,22 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from datetime import datetime + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = ["MeRetrieveResponse"] + + +class MeRetrieveResponse(BaseModel): + additional_credits_balance_usd: float = FieldInfo(alias="additionalCreditsBalanceUsd") + + monthly_credits_balance_usd: float = FieldInfo(alias="monthlyCreditsBalanceUsd") + + signed_up_at: datetime = FieldInfo(alias="signedUpAt") + + email: Optional[str] = None + + name: Optional[str] = None diff --git a/tests/api_resources/sessions/test_public_share.py b/tests/api_resources/sessions/test_public_share.py index 981c56d..1b877cb 100644 --- a/tests/api_resources/sessions/test_public_share.py +++ b/tests/api_resources/sessions/test_public_share.py @@ -7,9 +7,9 @@ import pytest -from browser_use import BrowserUse, AsyncBrowserUse from tests.utils import assert_matches_type -from browser_use.types.sessions import ShareView +from browser_use_sdk import BrowserUse, AsyncBrowserUse +from browser_use_sdk.types.sessions import ShareView base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -17,7 +17,7 @@ class TestPublicShare: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_method_create(self, client: BrowserUse) -> None: public_share = client.sessions.public_share.create( @@ -25,7 +25,7 @@ def test_method_create(self, client: BrowserUse) -> None: ) assert_matches_type(ShareView, public_share, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_raw_response_create(self, client: BrowserUse) -> None: response = client.sessions.public_share.with_raw_response.create( @@ -37,7 +37,7 @@ def test_raw_response_create(self, client: BrowserUse) -> None: public_share = response.parse() assert_matches_type(ShareView, public_share, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_streaming_response_create(self, client: BrowserUse) -> None: with client.sessions.public_share.with_streaming_response.create( @@ -51,7 +51,7 @@ def test_streaming_response_create(self, client: BrowserUse) -> None: assert cast(Any, response.is_closed) is True - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_path_params_create(self, client: BrowserUse) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"): @@ -59,7 +59,7 @@ def test_path_params_create(self, client: BrowserUse) -> None: "", ) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_method_retrieve(self, client: BrowserUse) -> None: public_share = client.sessions.public_share.retrieve( @@ -67,7 +67,7 @@ def test_method_retrieve(self, client: BrowserUse) -> None: ) assert_matches_type(ShareView, public_share, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_raw_response_retrieve(self, client: BrowserUse) -> None: response = client.sessions.public_share.with_raw_response.retrieve( @@ -79,7 +79,7 @@ def test_raw_response_retrieve(self, client: BrowserUse) -> None: public_share = response.parse() assert_matches_type(ShareView, public_share, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_streaming_response_retrieve(self, client: BrowserUse) -> None: with client.sessions.public_share.with_streaming_response.retrieve( @@ -93,7 +93,7 @@ def test_streaming_response_retrieve(self, client: BrowserUse) -> None: assert cast(Any, response.is_closed) is True - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_path_params_retrieve(self, client: BrowserUse) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"): @@ -101,15 +101,15 @@ def test_path_params_retrieve(self, client: BrowserUse) -> None: "", ) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_method_delete(self, client: BrowserUse) -> None: public_share = client.sessions.public_share.delete( "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) - assert_matches_type(object, public_share, path=["response"]) + assert public_share is None - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_raw_response_delete(self, client: BrowserUse) -> None: response = client.sessions.public_share.with_raw_response.delete( @@ -119,9 +119,9 @@ def test_raw_response_delete(self, client: BrowserUse) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" public_share = response.parse() - assert_matches_type(object, public_share, path=["response"]) + assert public_share is None - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_streaming_response_delete(self, client: BrowserUse) -> None: with client.sessions.public_share.with_streaming_response.delete( @@ -131,11 +131,11 @@ def test_streaming_response_delete(self, client: BrowserUse) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" public_share = response.parse() - assert_matches_type(object, public_share, path=["response"]) + assert public_share is None assert cast(Any, response.is_closed) is True - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_path_params_delete(self, client: BrowserUse) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"): @@ -149,7 +149,7 @@ class TestAsyncPublicShare: "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_method_create(self, async_client: AsyncBrowserUse) -> None: public_share = await async_client.sessions.public_share.create( @@ -157,7 +157,7 @@ async def test_method_create(self, async_client: AsyncBrowserUse) -> None: ) assert_matches_type(ShareView, public_share, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_raw_response_create(self, async_client: AsyncBrowserUse) -> None: response = await async_client.sessions.public_share.with_raw_response.create( @@ -169,7 +169,7 @@ async def test_raw_response_create(self, async_client: AsyncBrowserUse) -> None: public_share = await response.parse() assert_matches_type(ShareView, public_share, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_streaming_response_create(self, async_client: AsyncBrowserUse) -> None: async with async_client.sessions.public_share.with_streaming_response.create( @@ -183,7 +183,7 @@ async def test_streaming_response_create(self, async_client: AsyncBrowserUse) -> assert cast(Any, response.is_closed) is True - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_path_params_create(self, async_client: AsyncBrowserUse) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"): @@ -191,7 +191,7 @@ async def test_path_params_create(self, async_client: AsyncBrowserUse) -> None: "", ) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_method_retrieve(self, async_client: AsyncBrowserUse) -> None: public_share = await async_client.sessions.public_share.retrieve( @@ -199,7 +199,7 @@ async def test_method_retrieve(self, async_client: AsyncBrowserUse) -> None: ) assert_matches_type(ShareView, public_share, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_raw_response_retrieve(self, async_client: AsyncBrowserUse) -> None: response = await async_client.sessions.public_share.with_raw_response.retrieve( @@ -211,7 +211,7 @@ async def test_raw_response_retrieve(self, async_client: AsyncBrowserUse) -> Non public_share = await response.parse() assert_matches_type(ShareView, public_share, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncBrowserUse) -> None: async with async_client.sessions.public_share.with_streaming_response.retrieve( @@ -225,7 +225,7 @@ async def test_streaming_response_retrieve(self, async_client: AsyncBrowserUse) assert cast(Any, response.is_closed) is True - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_path_params_retrieve(self, async_client: AsyncBrowserUse) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"): @@ -233,15 +233,15 @@ async def test_path_params_retrieve(self, async_client: AsyncBrowserUse) -> None "", ) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_method_delete(self, async_client: AsyncBrowserUse) -> None: public_share = await async_client.sessions.public_share.delete( "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) - assert_matches_type(object, public_share, path=["response"]) + assert public_share is None - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_raw_response_delete(self, async_client: AsyncBrowserUse) -> None: response = await async_client.sessions.public_share.with_raw_response.delete( @@ -251,9 +251,9 @@ async def test_raw_response_delete(self, async_client: AsyncBrowserUse) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" public_share = await response.parse() - assert_matches_type(object, public_share, path=["response"]) + assert public_share is None - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_streaming_response_delete(self, async_client: AsyncBrowserUse) -> None: async with async_client.sessions.public_share.with_streaming_response.delete( @@ -263,11 +263,11 @@ async def test_streaming_response_delete(self, async_client: AsyncBrowserUse) -> assert response.http_request.headers.get("X-Stainless-Lang") == "python" public_share = await response.parse() - assert_matches_type(object, public_share, path=["response"]) + assert public_share is None assert cast(Any, response.is_closed) is True - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_path_params_delete(self, async_client: AsyncBrowserUse) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"): diff --git a/tests/api_resources/test_agent_profiles.py b/tests/api_resources/test_agent_profiles.py index 39ee837..77ee21c 100644 --- a/tests/api_resources/test_agent_profiles.py +++ b/tests/api_resources/test_agent_profiles.py @@ -7,9 +7,9 @@ import pytest -from browser_use import BrowserUse, AsyncBrowserUse from tests.utils import assert_matches_type -from browser_use.types import ( +from browser_use_sdk import BrowserUse, AsyncBrowserUse +from browser_use_sdk.types import ( AgentProfileView, AgentProfileListResponse, ) @@ -20,7 +20,7 @@ class TestAgentProfiles: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_method_create(self, client: BrowserUse) -> None: agent_profile = client.agent_profiles.create( @@ -28,23 +28,23 @@ def test_method_create(self, client: BrowserUse) -> None: ) assert_matches_type(AgentProfileView, agent_profile, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_method_create_with_all_params(self, client: BrowserUse) -> None: agent_profile = client.agent_profiles.create( name="x", allowed_domains=["string"], + custom_system_prompt_extension="x", description="x", flash_mode=True, highlight_elements=True, max_agent_steps=1, - system_prompt="x", thinking=True, vision=True, ) assert_matches_type(AgentProfileView, agent_profile, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_raw_response_create(self, client: BrowserUse) -> None: response = client.agent_profiles.with_raw_response.create( @@ -56,7 +56,7 @@ def test_raw_response_create(self, client: BrowserUse) -> None: agent_profile = response.parse() assert_matches_type(AgentProfileView, agent_profile, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_streaming_response_create(self, client: BrowserUse) -> None: with client.agent_profiles.with_streaming_response.create( @@ -70,7 +70,7 @@ def test_streaming_response_create(self, client: BrowserUse) -> None: assert cast(Any, response.is_closed) is True - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_method_retrieve(self, client: BrowserUse) -> None: agent_profile = client.agent_profiles.retrieve( @@ -78,7 +78,7 @@ def test_method_retrieve(self, client: BrowserUse) -> None: ) assert_matches_type(AgentProfileView, agent_profile, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_raw_response_retrieve(self, client: BrowserUse) -> None: response = client.agent_profiles.with_raw_response.retrieve( @@ -90,7 +90,7 @@ def test_raw_response_retrieve(self, client: BrowserUse) -> None: agent_profile = response.parse() assert_matches_type(AgentProfileView, agent_profile, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_streaming_response_retrieve(self, client: BrowserUse) -> None: with client.agent_profiles.with_streaming_response.retrieve( @@ -104,7 +104,7 @@ def test_streaming_response_retrieve(self, client: BrowserUse) -> None: assert cast(Any, response.is_closed) is True - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_path_params_retrieve(self, client: BrowserUse) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `profile_id` but received ''"): @@ -112,7 +112,7 @@ def test_path_params_retrieve(self, client: BrowserUse) -> None: "", ) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_method_update(self, client: BrowserUse) -> None: agent_profile = client.agent_profiles.update( @@ -120,24 +120,24 @@ def test_method_update(self, client: BrowserUse) -> None: ) assert_matches_type(AgentProfileView, agent_profile, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_method_update_with_all_params(self, client: BrowserUse) -> None: agent_profile = client.agent_profiles.update( profile_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", allowed_domains=["string"], + custom_system_prompt_extension="x", description="x", flash_mode=True, highlight_elements=True, max_agent_steps=1, name="x", - system_prompt="x", thinking=True, vision=True, ) assert_matches_type(AgentProfileView, agent_profile, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_raw_response_update(self, client: BrowserUse) -> None: response = client.agent_profiles.with_raw_response.update( @@ -149,7 +149,7 @@ def test_raw_response_update(self, client: BrowserUse) -> None: agent_profile = response.parse() assert_matches_type(AgentProfileView, agent_profile, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_streaming_response_update(self, client: BrowserUse) -> None: with client.agent_profiles.with_streaming_response.update( @@ -163,7 +163,7 @@ def test_streaming_response_update(self, client: BrowserUse) -> None: assert cast(Any, response.is_closed) is True - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_path_params_update(self, client: BrowserUse) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `profile_id` but received ''"): @@ -171,13 +171,13 @@ def test_path_params_update(self, client: BrowserUse) -> None: profile_id="", ) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_method_list(self, client: BrowserUse) -> None: agent_profile = client.agent_profiles.list() assert_matches_type(AgentProfileListResponse, agent_profile, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_method_list_with_all_params(self, client: BrowserUse) -> None: agent_profile = client.agent_profiles.list( @@ -186,7 +186,7 @@ def test_method_list_with_all_params(self, client: BrowserUse) -> None: ) assert_matches_type(AgentProfileListResponse, agent_profile, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_raw_response_list(self, client: BrowserUse) -> None: response = client.agent_profiles.with_raw_response.list() @@ -196,7 +196,7 @@ def test_raw_response_list(self, client: BrowserUse) -> None: agent_profile = response.parse() assert_matches_type(AgentProfileListResponse, agent_profile, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_streaming_response_list(self, client: BrowserUse) -> None: with client.agent_profiles.with_streaming_response.list() as response: @@ -208,15 +208,15 @@ def test_streaming_response_list(self, client: BrowserUse) -> None: assert cast(Any, response.is_closed) is True - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_method_delete(self, client: BrowserUse) -> None: agent_profile = client.agent_profiles.delete( "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) - assert_matches_type(object, agent_profile, path=["response"]) + assert agent_profile is None - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_raw_response_delete(self, client: BrowserUse) -> None: response = client.agent_profiles.with_raw_response.delete( @@ -226,9 +226,9 @@ def test_raw_response_delete(self, client: BrowserUse) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" agent_profile = response.parse() - assert_matches_type(object, agent_profile, path=["response"]) + assert agent_profile is None - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_streaming_response_delete(self, client: BrowserUse) -> None: with client.agent_profiles.with_streaming_response.delete( @@ -238,11 +238,11 @@ def test_streaming_response_delete(self, client: BrowserUse) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" agent_profile = response.parse() - assert_matches_type(object, agent_profile, path=["response"]) + assert agent_profile is None assert cast(Any, response.is_closed) is True - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_path_params_delete(self, client: BrowserUse) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `profile_id` but received ''"): @@ -256,7 +256,7 @@ class TestAsyncAgentProfiles: "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_method_create(self, async_client: AsyncBrowserUse) -> None: agent_profile = await async_client.agent_profiles.create( @@ -264,23 +264,23 @@ async def test_method_create(self, async_client: AsyncBrowserUse) -> None: ) assert_matches_type(AgentProfileView, agent_profile, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_method_create_with_all_params(self, async_client: AsyncBrowserUse) -> None: agent_profile = await async_client.agent_profiles.create( name="x", allowed_domains=["string"], + custom_system_prompt_extension="x", description="x", flash_mode=True, highlight_elements=True, max_agent_steps=1, - system_prompt="x", thinking=True, vision=True, ) assert_matches_type(AgentProfileView, agent_profile, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_raw_response_create(self, async_client: AsyncBrowserUse) -> None: response = await async_client.agent_profiles.with_raw_response.create( @@ -292,7 +292,7 @@ async def test_raw_response_create(self, async_client: AsyncBrowserUse) -> None: agent_profile = await response.parse() assert_matches_type(AgentProfileView, agent_profile, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_streaming_response_create(self, async_client: AsyncBrowserUse) -> None: async with async_client.agent_profiles.with_streaming_response.create( @@ -306,7 +306,7 @@ async def test_streaming_response_create(self, async_client: AsyncBrowserUse) -> assert cast(Any, response.is_closed) is True - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_method_retrieve(self, async_client: AsyncBrowserUse) -> None: agent_profile = await async_client.agent_profiles.retrieve( @@ -314,7 +314,7 @@ async def test_method_retrieve(self, async_client: AsyncBrowserUse) -> None: ) assert_matches_type(AgentProfileView, agent_profile, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_raw_response_retrieve(self, async_client: AsyncBrowserUse) -> None: response = await async_client.agent_profiles.with_raw_response.retrieve( @@ -326,7 +326,7 @@ async def test_raw_response_retrieve(self, async_client: AsyncBrowserUse) -> Non agent_profile = await response.parse() assert_matches_type(AgentProfileView, agent_profile, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncBrowserUse) -> None: async with async_client.agent_profiles.with_streaming_response.retrieve( @@ -340,7 +340,7 @@ async def test_streaming_response_retrieve(self, async_client: AsyncBrowserUse) assert cast(Any, response.is_closed) is True - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_path_params_retrieve(self, async_client: AsyncBrowserUse) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `profile_id` but received ''"): @@ -348,7 +348,7 @@ async def test_path_params_retrieve(self, async_client: AsyncBrowserUse) -> None "", ) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_method_update(self, async_client: AsyncBrowserUse) -> None: agent_profile = await async_client.agent_profiles.update( @@ -356,24 +356,24 @@ async def test_method_update(self, async_client: AsyncBrowserUse) -> None: ) assert_matches_type(AgentProfileView, agent_profile, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_method_update_with_all_params(self, async_client: AsyncBrowserUse) -> None: agent_profile = await async_client.agent_profiles.update( profile_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", allowed_domains=["string"], + custom_system_prompt_extension="x", description="x", flash_mode=True, highlight_elements=True, max_agent_steps=1, name="x", - system_prompt="x", thinking=True, vision=True, ) assert_matches_type(AgentProfileView, agent_profile, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_raw_response_update(self, async_client: AsyncBrowserUse) -> None: response = await async_client.agent_profiles.with_raw_response.update( @@ -385,7 +385,7 @@ async def test_raw_response_update(self, async_client: AsyncBrowserUse) -> None: agent_profile = await response.parse() assert_matches_type(AgentProfileView, agent_profile, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_streaming_response_update(self, async_client: AsyncBrowserUse) -> None: async with async_client.agent_profiles.with_streaming_response.update( @@ -399,7 +399,7 @@ async def test_streaming_response_update(self, async_client: AsyncBrowserUse) -> assert cast(Any, response.is_closed) is True - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_path_params_update(self, async_client: AsyncBrowserUse) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `profile_id` but received ''"): @@ -407,13 +407,13 @@ async def test_path_params_update(self, async_client: AsyncBrowserUse) -> None: profile_id="", ) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_method_list(self, async_client: AsyncBrowserUse) -> None: agent_profile = await async_client.agent_profiles.list() assert_matches_type(AgentProfileListResponse, agent_profile, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_method_list_with_all_params(self, async_client: AsyncBrowserUse) -> None: agent_profile = await async_client.agent_profiles.list( @@ -422,7 +422,7 @@ async def test_method_list_with_all_params(self, async_client: AsyncBrowserUse) ) assert_matches_type(AgentProfileListResponse, agent_profile, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_raw_response_list(self, async_client: AsyncBrowserUse) -> None: response = await async_client.agent_profiles.with_raw_response.list() @@ -432,7 +432,7 @@ async def test_raw_response_list(self, async_client: AsyncBrowserUse) -> None: agent_profile = await response.parse() assert_matches_type(AgentProfileListResponse, agent_profile, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_streaming_response_list(self, async_client: AsyncBrowserUse) -> None: async with async_client.agent_profiles.with_streaming_response.list() as response: @@ -444,15 +444,15 @@ async def test_streaming_response_list(self, async_client: AsyncBrowserUse) -> N assert cast(Any, response.is_closed) is True - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_method_delete(self, async_client: AsyncBrowserUse) -> None: agent_profile = await async_client.agent_profiles.delete( "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) - assert_matches_type(object, agent_profile, path=["response"]) + assert agent_profile is None - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_raw_response_delete(self, async_client: AsyncBrowserUse) -> None: response = await async_client.agent_profiles.with_raw_response.delete( @@ -462,9 +462,9 @@ async def test_raw_response_delete(self, async_client: AsyncBrowserUse) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" agent_profile = await response.parse() - assert_matches_type(object, agent_profile, path=["response"]) + assert agent_profile is None - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_streaming_response_delete(self, async_client: AsyncBrowserUse) -> None: async with async_client.agent_profiles.with_streaming_response.delete( @@ -474,11 +474,11 @@ async def test_streaming_response_delete(self, async_client: AsyncBrowserUse) -> assert response.http_request.headers.get("X-Stainless-Lang") == "python" agent_profile = await response.parse() - assert_matches_type(object, agent_profile, path=["response"]) + assert agent_profile is None assert cast(Any, response.is_closed) is True - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_path_params_delete(self, async_client: AsyncBrowserUse) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `profile_id` but received ''"): diff --git a/tests/api_resources/test_browser_profiles.py b/tests/api_resources/test_browser_profiles.py index 27df0d3..d10b16a 100644 --- a/tests/api_resources/test_browser_profiles.py +++ b/tests/api_resources/test_browser_profiles.py @@ -7,9 +7,9 @@ import pytest -from browser_use import BrowserUse, AsyncBrowserUse from tests.utils import assert_matches_type -from browser_use.types import ( +from browser_use_sdk import BrowserUse, AsyncBrowserUse +from browser_use_sdk.types import ( BrowserProfileView, BrowserProfileListResponse, ) @@ -20,7 +20,7 @@ class TestBrowserProfiles: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_method_create(self, client: BrowserUse) -> None: browser_profile = client.browser_profiles.create( @@ -28,7 +28,7 @@ def test_method_create(self, client: BrowserUse) -> None: ) assert_matches_type(BrowserProfileView, browser_profile, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_method_create_with_all_params(self, client: BrowserUse) -> None: browser_profile = client.browser_profiles.create( @@ -45,7 +45,7 @@ def test_method_create_with_all_params(self, client: BrowserUse) -> None: ) assert_matches_type(BrowserProfileView, browser_profile, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_raw_response_create(self, client: BrowserUse) -> None: response = client.browser_profiles.with_raw_response.create( @@ -57,7 +57,7 @@ def test_raw_response_create(self, client: BrowserUse) -> None: browser_profile = response.parse() assert_matches_type(BrowserProfileView, browser_profile, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_streaming_response_create(self, client: BrowserUse) -> None: with client.browser_profiles.with_streaming_response.create( @@ -71,7 +71,7 @@ def test_streaming_response_create(self, client: BrowserUse) -> None: assert cast(Any, response.is_closed) is True - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_method_retrieve(self, client: BrowserUse) -> None: browser_profile = client.browser_profiles.retrieve( @@ -79,7 +79,7 @@ def test_method_retrieve(self, client: BrowserUse) -> None: ) assert_matches_type(BrowserProfileView, browser_profile, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_raw_response_retrieve(self, client: BrowserUse) -> None: response = client.browser_profiles.with_raw_response.retrieve( @@ -91,7 +91,7 @@ def test_raw_response_retrieve(self, client: BrowserUse) -> None: browser_profile = response.parse() assert_matches_type(BrowserProfileView, browser_profile, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_streaming_response_retrieve(self, client: BrowserUse) -> None: with client.browser_profiles.with_streaming_response.retrieve( @@ -105,7 +105,7 @@ def test_streaming_response_retrieve(self, client: BrowserUse) -> None: assert cast(Any, response.is_closed) is True - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_path_params_retrieve(self, client: BrowserUse) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `profile_id` but received ''"): @@ -113,7 +113,7 @@ def test_path_params_retrieve(self, client: BrowserUse) -> None: "", ) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_method_update(self, client: BrowserUse) -> None: browser_profile = client.browser_profiles.update( @@ -121,7 +121,7 @@ def test_method_update(self, client: BrowserUse) -> None: ) assert_matches_type(BrowserProfileView, browser_profile, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_method_update_with_all_params(self, client: BrowserUse) -> None: browser_profile = client.browser_profiles.update( @@ -139,7 +139,7 @@ def test_method_update_with_all_params(self, client: BrowserUse) -> None: ) assert_matches_type(BrowserProfileView, browser_profile, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_raw_response_update(self, client: BrowserUse) -> None: response = client.browser_profiles.with_raw_response.update( @@ -151,7 +151,7 @@ def test_raw_response_update(self, client: BrowserUse) -> None: browser_profile = response.parse() assert_matches_type(BrowserProfileView, browser_profile, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_streaming_response_update(self, client: BrowserUse) -> None: with client.browser_profiles.with_streaming_response.update( @@ -165,7 +165,7 @@ def test_streaming_response_update(self, client: BrowserUse) -> None: assert cast(Any, response.is_closed) is True - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_path_params_update(self, client: BrowserUse) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `profile_id` but received ''"): @@ -173,13 +173,13 @@ def test_path_params_update(self, client: BrowserUse) -> None: profile_id="", ) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_method_list(self, client: BrowserUse) -> None: browser_profile = client.browser_profiles.list() assert_matches_type(BrowserProfileListResponse, browser_profile, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_method_list_with_all_params(self, client: BrowserUse) -> None: browser_profile = client.browser_profiles.list( @@ -188,7 +188,7 @@ def test_method_list_with_all_params(self, client: BrowserUse) -> None: ) assert_matches_type(BrowserProfileListResponse, browser_profile, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_raw_response_list(self, client: BrowserUse) -> None: response = client.browser_profiles.with_raw_response.list() @@ -198,7 +198,7 @@ def test_raw_response_list(self, client: BrowserUse) -> None: browser_profile = response.parse() assert_matches_type(BrowserProfileListResponse, browser_profile, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_streaming_response_list(self, client: BrowserUse) -> None: with client.browser_profiles.with_streaming_response.list() as response: @@ -210,15 +210,15 @@ def test_streaming_response_list(self, client: BrowserUse) -> None: assert cast(Any, response.is_closed) is True - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_method_delete(self, client: BrowserUse) -> None: browser_profile = client.browser_profiles.delete( "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) - assert_matches_type(object, browser_profile, path=["response"]) + assert browser_profile is None - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_raw_response_delete(self, client: BrowserUse) -> None: response = client.browser_profiles.with_raw_response.delete( @@ -228,9 +228,9 @@ def test_raw_response_delete(self, client: BrowserUse) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" browser_profile = response.parse() - assert_matches_type(object, browser_profile, path=["response"]) + assert browser_profile is None - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_streaming_response_delete(self, client: BrowserUse) -> None: with client.browser_profiles.with_streaming_response.delete( @@ -240,11 +240,11 @@ def test_streaming_response_delete(self, client: BrowserUse) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" browser_profile = response.parse() - assert_matches_type(object, browser_profile, path=["response"]) + assert browser_profile is None assert cast(Any, response.is_closed) is True - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_path_params_delete(self, client: BrowserUse) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `profile_id` but received ''"): @@ -258,7 +258,7 @@ class TestAsyncBrowserProfiles: "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_method_create(self, async_client: AsyncBrowserUse) -> None: browser_profile = await async_client.browser_profiles.create( @@ -266,7 +266,7 @@ async def test_method_create(self, async_client: AsyncBrowserUse) -> None: ) assert_matches_type(BrowserProfileView, browser_profile, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_method_create_with_all_params(self, async_client: AsyncBrowserUse) -> None: browser_profile = await async_client.browser_profiles.create( @@ -283,7 +283,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncBrowserUse ) assert_matches_type(BrowserProfileView, browser_profile, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_raw_response_create(self, async_client: AsyncBrowserUse) -> None: response = await async_client.browser_profiles.with_raw_response.create( @@ -295,7 +295,7 @@ async def test_raw_response_create(self, async_client: AsyncBrowserUse) -> None: browser_profile = await response.parse() assert_matches_type(BrowserProfileView, browser_profile, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_streaming_response_create(self, async_client: AsyncBrowserUse) -> None: async with async_client.browser_profiles.with_streaming_response.create( @@ -309,7 +309,7 @@ async def test_streaming_response_create(self, async_client: AsyncBrowserUse) -> assert cast(Any, response.is_closed) is True - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_method_retrieve(self, async_client: AsyncBrowserUse) -> None: browser_profile = await async_client.browser_profiles.retrieve( @@ -317,7 +317,7 @@ async def test_method_retrieve(self, async_client: AsyncBrowserUse) -> None: ) assert_matches_type(BrowserProfileView, browser_profile, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_raw_response_retrieve(self, async_client: AsyncBrowserUse) -> None: response = await async_client.browser_profiles.with_raw_response.retrieve( @@ -329,7 +329,7 @@ async def test_raw_response_retrieve(self, async_client: AsyncBrowserUse) -> Non browser_profile = await response.parse() assert_matches_type(BrowserProfileView, browser_profile, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncBrowserUse) -> None: async with async_client.browser_profiles.with_streaming_response.retrieve( @@ -343,7 +343,7 @@ async def test_streaming_response_retrieve(self, async_client: AsyncBrowserUse) assert cast(Any, response.is_closed) is True - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_path_params_retrieve(self, async_client: AsyncBrowserUse) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `profile_id` but received ''"): @@ -351,7 +351,7 @@ async def test_path_params_retrieve(self, async_client: AsyncBrowserUse) -> None "", ) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_method_update(self, async_client: AsyncBrowserUse) -> None: browser_profile = await async_client.browser_profiles.update( @@ -359,7 +359,7 @@ async def test_method_update(self, async_client: AsyncBrowserUse) -> None: ) assert_matches_type(BrowserProfileView, browser_profile, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_method_update_with_all_params(self, async_client: AsyncBrowserUse) -> None: browser_profile = await async_client.browser_profiles.update( @@ -377,7 +377,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncBrowserUse ) assert_matches_type(BrowserProfileView, browser_profile, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_raw_response_update(self, async_client: AsyncBrowserUse) -> None: response = await async_client.browser_profiles.with_raw_response.update( @@ -389,7 +389,7 @@ async def test_raw_response_update(self, async_client: AsyncBrowserUse) -> None: browser_profile = await response.parse() assert_matches_type(BrowserProfileView, browser_profile, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_streaming_response_update(self, async_client: AsyncBrowserUse) -> None: async with async_client.browser_profiles.with_streaming_response.update( @@ -403,7 +403,7 @@ async def test_streaming_response_update(self, async_client: AsyncBrowserUse) -> assert cast(Any, response.is_closed) is True - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_path_params_update(self, async_client: AsyncBrowserUse) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `profile_id` but received ''"): @@ -411,13 +411,13 @@ async def test_path_params_update(self, async_client: AsyncBrowserUse) -> None: profile_id="", ) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_method_list(self, async_client: AsyncBrowserUse) -> None: browser_profile = await async_client.browser_profiles.list() assert_matches_type(BrowserProfileListResponse, browser_profile, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_method_list_with_all_params(self, async_client: AsyncBrowserUse) -> None: browser_profile = await async_client.browser_profiles.list( @@ -426,7 +426,7 @@ async def test_method_list_with_all_params(self, async_client: AsyncBrowserUse) ) assert_matches_type(BrowserProfileListResponse, browser_profile, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_raw_response_list(self, async_client: AsyncBrowserUse) -> None: response = await async_client.browser_profiles.with_raw_response.list() @@ -436,7 +436,7 @@ async def test_raw_response_list(self, async_client: AsyncBrowserUse) -> None: browser_profile = await response.parse() assert_matches_type(BrowserProfileListResponse, browser_profile, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_streaming_response_list(self, async_client: AsyncBrowserUse) -> None: async with async_client.browser_profiles.with_streaming_response.list() as response: @@ -448,15 +448,15 @@ async def test_streaming_response_list(self, async_client: AsyncBrowserUse) -> N assert cast(Any, response.is_closed) is True - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_method_delete(self, async_client: AsyncBrowserUse) -> None: browser_profile = await async_client.browser_profiles.delete( "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) - assert_matches_type(object, browser_profile, path=["response"]) + assert browser_profile is None - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_raw_response_delete(self, async_client: AsyncBrowserUse) -> None: response = await async_client.browser_profiles.with_raw_response.delete( @@ -466,9 +466,9 @@ async def test_raw_response_delete(self, async_client: AsyncBrowserUse) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" browser_profile = await response.parse() - assert_matches_type(object, browser_profile, path=["response"]) + assert browser_profile is None - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_streaming_response_delete(self, async_client: AsyncBrowserUse) -> None: async with async_client.browser_profiles.with_streaming_response.delete( @@ -478,11 +478,11 @@ async def test_streaming_response_delete(self, async_client: AsyncBrowserUse) -> assert response.http_request.headers.get("X-Stainless-Lang") == "python" browser_profile = await response.parse() - assert_matches_type(object, browser_profile, path=["response"]) + assert browser_profile is None assert cast(Any, response.is_closed) is True - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_path_params_delete(self, async_client: AsyncBrowserUse) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `profile_id` but received ''"): diff --git a/tests/api_resources/test_sessions.py b/tests/api_resources/test_sessions.py index 7e17295..0751000 100644 --- a/tests/api_resources/test_sessions.py +++ b/tests/api_resources/test_sessions.py @@ -7,9 +7,9 @@ import pytest -from browser_use import BrowserUse, AsyncBrowserUse from tests.utils import assert_matches_type -from browser_use.types import ( +from browser_use_sdk import BrowserUse, AsyncBrowserUse +from browser_use_sdk.types import ( SessionView, SessionListResponse, ) @@ -20,28 +20,19 @@ class TestSessions: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_method_retrieve(self, client: BrowserUse) -> None: session = client.sessions.retrieve( - session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) assert_matches_type(SessionView, session, path=["response"]) - @pytest.mark.skip() - @parametrize - def test_method_retrieve_with_all_params(self, client: BrowserUse) -> None: - session = client.sessions.retrieve( - session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - include_tasks=True, - ) - assert_matches_type(SessionView, session, path=["response"]) - - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_raw_response_retrieve(self, client: BrowserUse) -> None: response = client.sessions.with_raw_response.retrieve( - session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) assert response.is_closed is True @@ -49,11 +40,11 @@ def test_raw_response_retrieve(self, client: BrowserUse) -> None: session = response.parse() assert_matches_type(SessionView, session, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_streaming_response_retrieve(self, client: BrowserUse) -> None: with client.sessions.with_streaming_response.retrieve( - session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -63,15 +54,15 @@ def test_streaming_response_retrieve(self, client: BrowserUse) -> None: assert cast(Any, response.is_closed) is True - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_path_params_retrieve(self, client: BrowserUse) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"): client.sessions.with_raw_response.retrieve( - session_id="", + "", ) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_method_update(self, client: BrowserUse) -> None: session = client.sessions.update( @@ -80,7 +71,7 @@ def test_method_update(self, client: BrowserUse) -> None: ) assert_matches_type(SessionView, session, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_raw_response_update(self, client: BrowserUse) -> None: response = client.sessions.with_raw_response.update( @@ -93,7 +84,7 @@ def test_raw_response_update(self, client: BrowserUse) -> None: session = response.parse() assert_matches_type(SessionView, session, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_streaming_response_update(self, client: BrowserUse) -> None: with client.sessions.with_streaming_response.update( @@ -108,7 +99,7 @@ def test_streaming_response_update(self, client: BrowserUse) -> None: assert cast(Any, response.is_closed) is True - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_path_params_update(self, client: BrowserUse) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"): @@ -117,24 +108,23 @@ def test_path_params_update(self, client: BrowserUse) -> None: action="stop", ) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_method_list(self, client: BrowserUse) -> None: session = client.sessions.list() assert_matches_type(SessionListResponse, session, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_method_list_with_all_params(self, client: BrowserUse) -> None: session = client.sessions.list( filter_by="active", - include_tasks=True, page_number=1, page_size=1, ) assert_matches_type(SessionListResponse, session, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_raw_response_list(self, client: BrowserUse) -> None: response = client.sessions.with_raw_response.list() @@ -144,7 +134,7 @@ def test_raw_response_list(self, client: BrowserUse) -> None: session = response.parse() assert_matches_type(SessionListResponse, session, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_streaming_response_list(self, client: BrowserUse) -> None: with client.sessions.with_streaming_response.list() as response: @@ -156,34 +146,67 @@ def test_streaming_response_list(self, client: BrowserUse) -> None: assert cast(Any, response.is_closed) is True + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_delete(self, client: BrowserUse) -> None: + session = client.sessions.delete( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert session is None + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_delete(self, client: BrowserUse) -> None: + response = client.sessions.with_raw_response.delete( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + session = response.parse() + assert session is None + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_delete(self, client: BrowserUse) -> None: + with client.sessions.with_streaming_response.delete( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + session = response.parse() + assert session is None + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_delete(self, client: BrowserUse) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"): + client.sessions.with_raw_response.delete( + "", + ) + class TestAsyncSessions: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_method_retrieve(self, async_client: AsyncBrowserUse) -> None: session = await async_client.sessions.retrieve( - session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) assert_matches_type(SessionView, session, path=["response"]) - @pytest.mark.skip() - @parametrize - async def test_method_retrieve_with_all_params(self, async_client: AsyncBrowserUse) -> None: - session = await async_client.sessions.retrieve( - session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - include_tasks=True, - ) - assert_matches_type(SessionView, session, path=["response"]) - - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_raw_response_retrieve(self, async_client: AsyncBrowserUse) -> None: response = await async_client.sessions.with_raw_response.retrieve( - session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) assert response.is_closed is True @@ -191,11 +214,11 @@ async def test_raw_response_retrieve(self, async_client: AsyncBrowserUse) -> Non session = await response.parse() assert_matches_type(SessionView, session, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncBrowserUse) -> None: async with async_client.sessions.with_streaming_response.retrieve( - session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -205,15 +228,15 @@ async def test_streaming_response_retrieve(self, async_client: AsyncBrowserUse) assert cast(Any, response.is_closed) is True - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_path_params_retrieve(self, async_client: AsyncBrowserUse) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"): await async_client.sessions.with_raw_response.retrieve( - session_id="", + "", ) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_method_update(self, async_client: AsyncBrowserUse) -> None: session = await async_client.sessions.update( @@ -222,7 +245,7 @@ async def test_method_update(self, async_client: AsyncBrowserUse) -> None: ) assert_matches_type(SessionView, session, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_raw_response_update(self, async_client: AsyncBrowserUse) -> None: response = await async_client.sessions.with_raw_response.update( @@ -235,7 +258,7 @@ async def test_raw_response_update(self, async_client: AsyncBrowserUse) -> None: session = await response.parse() assert_matches_type(SessionView, session, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_streaming_response_update(self, async_client: AsyncBrowserUse) -> None: async with async_client.sessions.with_streaming_response.update( @@ -250,7 +273,7 @@ async def test_streaming_response_update(self, async_client: AsyncBrowserUse) -> assert cast(Any, response.is_closed) is True - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_path_params_update(self, async_client: AsyncBrowserUse) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"): @@ -259,24 +282,23 @@ async def test_path_params_update(self, async_client: AsyncBrowserUse) -> None: action="stop", ) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_method_list(self, async_client: AsyncBrowserUse) -> None: session = await async_client.sessions.list() assert_matches_type(SessionListResponse, session, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_method_list_with_all_params(self, async_client: AsyncBrowserUse) -> None: session = await async_client.sessions.list( filter_by="active", - include_tasks=True, page_number=1, page_size=1, ) assert_matches_type(SessionListResponse, session, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_raw_response_list(self, async_client: AsyncBrowserUse) -> None: response = await async_client.sessions.with_raw_response.list() @@ -286,7 +308,7 @@ async def test_raw_response_list(self, async_client: AsyncBrowserUse) -> None: session = await response.parse() assert_matches_type(SessionListResponse, session, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_streaming_response_list(self, async_client: AsyncBrowserUse) -> None: async with async_client.sessions.with_streaming_response.list() as response: @@ -297,3 +319,45 @@ async def test_streaming_response_list(self, async_client: AsyncBrowserUse) -> N assert_matches_type(SessionListResponse, session, path=["response"]) assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_delete(self, async_client: AsyncBrowserUse) -> None: + session = await async_client.sessions.delete( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert session is None + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_delete(self, async_client: AsyncBrowserUse) -> None: + response = await async_client.sessions.with_raw_response.delete( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + session = await response.parse() + assert session is None + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_delete(self, async_client: AsyncBrowserUse) -> None: + async with async_client.sessions.with_streaming_response.delete( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + session = await response.parse() + assert session is None + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_delete(self, async_client: AsyncBrowserUse) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"): + await async_client.sessions.with_raw_response.delete( + "", + ) diff --git a/tests/api_resources/test_tasks.py b/tests/api_resources/test_tasks.py index 9944a33..d03ca35 100644 --- a/tests/api_resources/test_tasks.py +++ b/tests/api_resources/test_tasks.py @@ -7,15 +7,17 @@ import pytest -from browser_use import BrowserUse, AsyncBrowserUse from tests.utils import assert_matches_type -from browser_use.types import ( +from browser_use_sdk import BrowserUse, AsyncBrowserUse +from browser_use_sdk.types import ( TaskView, TaskListResponse, - TaskRetrieveResponse, - TaskRetrieveLogsResponse, - TaskRetrieveOutputFileResponse, + TaskCreateResponse, + TaskGetLogsResponse, + TaskGetOutputFileResponse, + TaskGetUserUploadedFileResponse, ) +from browser_use_sdk._utils import parse_datetime base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -23,15 +25,15 @@ class TestTasks: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_method_create(self, client: BrowserUse) -> None: task = client.tasks.create( task="x", ) - assert_matches_type(TaskView, task, path=["response"]) + assert_matches_type(TaskCreateResponse, task, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_method_create_with_all_params(self, client: BrowserUse) -> None: task = client.tasks.create( @@ -39,10 +41,10 @@ def test_method_create_with_all_params(self, client: BrowserUse) -> None: agent_settings={ "llm": "gpt-4o", "profile_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + "start_url": "startUrl", }, browser_settings={ "profile_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - "save_browser_data": True, "session_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", }, included_file_names=["string"], @@ -50,9 +52,9 @@ def test_method_create_with_all_params(self, client: BrowserUse) -> None: secrets={"foo": "string"}, structured_output_json="structuredOutputJson", ) - assert_matches_type(TaskView, task, path=["response"]) + assert_matches_type(TaskCreateResponse, task, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_raw_response_create(self, client: BrowserUse) -> None: response = client.tasks.with_raw_response.create( @@ -62,9 +64,9 @@ def test_raw_response_create(self, client: BrowserUse) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" task = response.parse() - assert_matches_type(TaskView, task, path=["response"]) + assert_matches_type(TaskCreateResponse, task, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_streaming_response_create(self, client: BrowserUse) -> None: with client.tasks.with_streaming_response.create( @@ -74,62 +76,53 @@ def test_streaming_response_create(self, client: BrowserUse) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" task = response.parse() - assert_matches_type(TaskView, task, path=["response"]) + assert_matches_type(TaskCreateResponse, task, path=["response"]) assert cast(Any, response.is_closed) is True - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_method_retrieve(self, client: BrowserUse) -> None: task = client.tasks.retrieve( - task_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - assert_matches_type(TaskRetrieveResponse, task, path=["response"]) - - @pytest.mark.skip() - @parametrize - def test_method_retrieve_with_all_params(self, client: BrowserUse) -> None: - task = client.tasks.retrieve( - task_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - status_only=True, + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) - assert_matches_type(TaskRetrieveResponse, task, path=["response"]) + assert_matches_type(TaskView, task, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_raw_response_retrieve(self, client: BrowserUse) -> None: response = client.tasks.with_raw_response.retrieve( - task_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" task = response.parse() - assert_matches_type(TaskRetrieveResponse, task, path=["response"]) + assert_matches_type(TaskView, task, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_streaming_response_retrieve(self, client: BrowserUse) -> None: with client.tasks.with_streaming_response.retrieve( - task_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" task = response.parse() - assert_matches_type(TaskRetrieveResponse, task, path=["response"]) + assert_matches_type(TaskView, task, path=["response"]) assert cast(Any, response.is_closed) is True - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_path_params_retrieve(self, client: BrowserUse) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `task_id` but received ''"): client.tasks.with_raw_response.retrieve( - task_id="", + "", ) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_method_update(self, client: BrowserUse) -> None: task = client.tasks.update( @@ -138,7 +131,7 @@ def test_method_update(self, client: BrowserUse) -> None: ) assert_matches_type(TaskView, task, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_raw_response_update(self, client: BrowserUse) -> None: response = client.tasks.with_raw_response.update( @@ -151,7 +144,7 @@ def test_raw_response_update(self, client: BrowserUse) -> None: task = response.parse() assert_matches_type(TaskView, task, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_streaming_response_update(self, client: BrowserUse) -> None: with client.tasks.with_streaming_response.update( @@ -166,7 +159,7 @@ def test_streaming_response_update(self, client: BrowserUse) -> None: assert cast(Any, response.is_closed) is True - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_path_params_update(self, client: BrowserUse) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `task_id` but received ''"): @@ -175,25 +168,26 @@ def test_path_params_update(self, client: BrowserUse) -> None: action="stop", ) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_method_list(self, client: BrowserUse) -> None: task = client.tasks.list() assert_matches_type(TaskListResponse, task, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_method_list_with_all_params(self, client: BrowserUse) -> None: task = client.tasks.list( - include_output_files=True, - include_steps=True, - include_user_uploaded_files=True, + after=parse_datetime("2019-12-27T18:11:19.117Z"), + before=parse_datetime("2019-12-27T18:11:19.117Z"), + filter_by="started", page_number=1, page_size=1, + session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) assert_matches_type(TaskListResponse, task, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_raw_response_list(self, client: BrowserUse) -> None: response = client.tasks.with_raw_response.list() @@ -203,7 +197,7 @@ def test_raw_response_list(self, client: BrowserUse) -> None: task = response.parse() assert_matches_type(TaskListResponse, task, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize def test_streaming_response_list(self, client: BrowserUse) -> None: with client.tasks.with_streaming_response.list() as response: @@ -215,97 +209,149 @@ def test_streaming_response_list(self, client: BrowserUse) -> None: assert cast(Any, response.is_closed) is True - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_retrieve_logs(self, client: BrowserUse) -> None: - task = client.tasks.retrieve_logs( + def test_method_get_logs(self, client: BrowserUse) -> None: + task = client.tasks.get_logs( "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) - assert_matches_type(TaskRetrieveLogsResponse, task, path=["response"]) + assert_matches_type(TaskGetLogsResponse, task, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_raw_response_retrieve_logs(self, client: BrowserUse) -> None: - response = client.tasks.with_raw_response.retrieve_logs( + def test_raw_response_get_logs(self, client: BrowserUse) -> None: + response = client.tasks.with_raw_response.get_logs( "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" task = response.parse() - assert_matches_type(TaskRetrieveLogsResponse, task, path=["response"]) + assert_matches_type(TaskGetLogsResponse, task, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_streaming_response_retrieve_logs(self, client: BrowserUse) -> None: - with client.tasks.with_streaming_response.retrieve_logs( + def test_streaming_response_get_logs(self, client: BrowserUse) -> None: + with client.tasks.with_streaming_response.get_logs( "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" task = response.parse() - assert_matches_type(TaskRetrieveLogsResponse, task, path=["response"]) + assert_matches_type(TaskGetLogsResponse, task, path=["response"]) assert cast(Any, response.is_closed) is True - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_path_params_retrieve_logs(self, client: BrowserUse) -> None: + def test_path_params_get_logs(self, client: BrowserUse) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `task_id` but received ''"): - client.tasks.with_raw_response.retrieve_logs( + client.tasks.with_raw_response.get_logs( "", ) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_get_output_file(self, client: BrowserUse) -> None: + task = client.tasks.get_output_file( + file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + task_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert_matches_type(TaskGetOutputFileResponse, task, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_get_output_file(self, client: BrowserUse) -> None: + response = client.tasks.with_raw_response.get_output_file( + file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + task_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + task = response.parse() + assert_matches_type(TaskGetOutputFileResponse, task, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_get_output_file(self, client: BrowserUse) -> None: + with client.tasks.with_streaming_response.get_output_file( + file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + task_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + task = response.parse() + assert_matches_type(TaskGetOutputFileResponse, task, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_get_output_file(self, client: BrowserUse) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `task_id` but received ''"): + client.tasks.with_raw_response.get_output_file( + file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + task_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): + client.tasks.with_raw_response.get_output_file( + file_id="", + task_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_method_retrieve_output_file(self, client: BrowserUse) -> None: - task = client.tasks.retrieve_output_file( - file_name="file_name", + def test_method_get_user_uploaded_file(self, client: BrowserUse) -> None: + task = client.tasks.get_user_uploaded_file( + file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", task_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) - assert_matches_type(TaskRetrieveOutputFileResponse, task, path=["response"]) + assert_matches_type(TaskGetUserUploadedFileResponse, task, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_raw_response_retrieve_output_file(self, client: BrowserUse) -> None: - response = client.tasks.with_raw_response.retrieve_output_file( - file_name="file_name", + def test_raw_response_get_user_uploaded_file(self, client: BrowserUse) -> None: + response = client.tasks.with_raw_response.get_user_uploaded_file( + file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", task_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" task = response.parse() - assert_matches_type(TaskRetrieveOutputFileResponse, task, path=["response"]) + assert_matches_type(TaskGetUserUploadedFileResponse, task, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_streaming_response_retrieve_output_file(self, client: BrowserUse) -> None: - with client.tasks.with_streaming_response.retrieve_output_file( - file_name="file_name", + def test_streaming_response_get_user_uploaded_file(self, client: BrowserUse) -> None: + with client.tasks.with_streaming_response.get_user_uploaded_file( + file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", task_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" task = response.parse() - assert_matches_type(TaskRetrieveOutputFileResponse, task, path=["response"]) + assert_matches_type(TaskGetUserUploadedFileResponse, task, path=["response"]) assert cast(Any, response.is_closed) is True - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - def test_path_params_retrieve_output_file(self, client: BrowserUse) -> None: + def test_path_params_get_user_uploaded_file(self, client: BrowserUse) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `task_id` but received ''"): - client.tasks.with_raw_response.retrieve_output_file( - file_name="file_name", + client.tasks.with_raw_response.get_user_uploaded_file( + file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", task_id="", ) - with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_name` but received ''"): - client.tasks.with_raw_response.retrieve_output_file( - file_name="", + with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): + client.tasks.with_raw_response.get_user_uploaded_file( + file_id="", task_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) @@ -315,15 +361,15 @@ class TestAsyncTasks: "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_method_create(self, async_client: AsyncBrowserUse) -> None: task = await async_client.tasks.create( task="x", ) - assert_matches_type(TaskView, task, path=["response"]) + assert_matches_type(TaskCreateResponse, task, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_method_create_with_all_params(self, async_client: AsyncBrowserUse) -> None: task = await async_client.tasks.create( @@ -331,10 +377,10 @@ async def test_method_create_with_all_params(self, async_client: AsyncBrowserUse agent_settings={ "llm": "gpt-4o", "profile_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + "start_url": "startUrl", }, browser_settings={ "profile_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - "save_browser_data": True, "session_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", }, included_file_names=["string"], @@ -342,9 +388,9 @@ async def test_method_create_with_all_params(self, async_client: AsyncBrowserUse secrets={"foo": "string"}, structured_output_json="structuredOutputJson", ) - assert_matches_type(TaskView, task, path=["response"]) + assert_matches_type(TaskCreateResponse, task, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_raw_response_create(self, async_client: AsyncBrowserUse) -> None: response = await async_client.tasks.with_raw_response.create( @@ -354,9 +400,9 @@ async def test_raw_response_create(self, async_client: AsyncBrowserUse) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" task = await response.parse() - assert_matches_type(TaskView, task, path=["response"]) + assert_matches_type(TaskCreateResponse, task, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_streaming_response_create(self, async_client: AsyncBrowserUse) -> None: async with async_client.tasks.with_streaming_response.create( @@ -366,62 +412,53 @@ async def test_streaming_response_create(self, async_client: AsyncBrowserUse) -> assert response.http_request.headers.get("X-Stainless-Lang") == "python" task = await response.parse() - assert_matches_type(TaskView, task, path=["response"]) + assert_matches_type(TaskCreateResponse, task, path=["response"]) assert cast(Any, response.is_closed) is True - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_method_retrieve(self, async_client: AsyncBrowserUse) -> None: task = await async_client.tasks.retrieve( - task_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - ) - assert_matches_type(TaskRetrieveResponse, task, path=["response"]) - - @pytest.mark.skip() - @parametrize - async def test_method_retrieve_with_all_params(self, async_client: AsyncBrowserUse) -> None: - task = await async_client.tasks.retrieve( - task_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - status_only=True, + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) - assert_matches_type(TaskRetrieveResponse, task, path=["response"]) + assert_matches_type(TaskView, task, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_raw_response_retrieve(self, async_client: AsyncBrowserUse) -> None: response = await async_client.tasks.with_raw_response.retrieve( - task_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" task = await response.parse() - assert_matches_type(TaskRetrieveResponse, task, path=["response"]) + assert_matches_type(TaskView, task, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncBrowserUse) -> None: async with async_client.tasks.with_streaming_response.retrieve( - task_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" task = await response.parse() - assert_matches_type(TaskRetrieveResponse, task, path=["response"]) + assert_matches_type(TaskView, task, path=["response"]) assert cast(Any, response.is_closed) is True - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_path_params_retrieve(self, async_client: AsyncBrowserUse) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `task_id` but received ''"): await async_client.tasks.with_raw_response.retrieve( - task_id="", + "", ) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_method_update(self, async_client: AsyncBrowserUse) -> None: task = await async_client.tasks.update( @@ -430,7 +467,7 @@ async def test_method_update(self, async_client: AsyncBrowserUse) -> None: ) assert_matches_type(TaskView, task, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_raw_response_update(self, async_client: AsyncBrowserUse) -> None: response = await async_client.tasks.with_raw_response.update( @@ -443,7 +480,7 @@ async def test_raw_response_update(self, async_client: AsyncBrowserUse) -> None: task = await response.parse() assert_matches_type(TaskView, task, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_streaming_response_update(self, async_client: AsyncBrowserUse) -> None: async with async_client.tasks.with_streaming_response.update( @@ -458,7 +495,7 @@ async def test_streaming_response_update(self, async_client: AsyncBrowserUse) -> assert cast(Any, response.is_closed) is True - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_path_params_update(self, async_client: AsyncBrowserUse) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `task_id` but received ''"): @@ -467,25 +504,26 @@ async def test_path_params_update(self, async_client: AsyncBrowserUse) -> None: action="stop", ) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_method_list(self, async_client: AsyncBrowserUse) -> None: task = await async_client.tasks.list() assert_matches_type(TaskListResponse, task, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_method_list_with_all_params(self, async_client: AsyncBrowserUse) -> None: task = await async_client.tasks.list( - include_output_files=True, - include_steps=True, - include_user_uploaded_files=True, + after=parse_datetime("2019-12-27T18:11:19.117Z"), + before=parse_datetime("2019-12-27T18:11:19.117Z"), + filter_by="started", page_number=1, page_size=1, + session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) assert_matches_type(TaskListResponse, task, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_raw_response_list(self, async_client: AsyncBrowserUse) -> None: response = await async_client.tasks.with_raw_response.list() @@ -495,7 +533,7 @@ async def test_raw_response_list(self, async_client: AsyncBrowserUse) -> None: task = await response.parse() assert_matches_type(TaskListResponse, task, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize async def test_streaming_response_list(self, async_client: AsyncBrowserUse) -> None: async with async_client.tasks.with_streaming_response.list() as response: @@ -507,96 +545,148 @@ async def test_streaming_response_list(self, async_client: AsyncBrowserUse) -> N assert cast(Any, response.is_closed) is True - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_method_retrieve_logs(self, async_client: AsyncBrowserUse) -> None: - task = await async_client.tasks.retrieve_logs( + async def test_method_get_logs(self, async_client: AsyncBrowserUse) -> None: + task = await async_client.tasks.get_logs( "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) - assert_matches_type(TaskRetrieveLogsResponse, task, path=["response"]) + assert_matches_type(TaskGetLogsResponse, task, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_raw_response_retrieve_logs(self, async_client: AsyncBrowserUse) -> None: - response = await async_client.tasks.with_raw_response.retrieve_logs( + async def test_raw_response_get_logs(self, async_client: AsyncBrowserUse) -> None: + response = await async_client.tasks.with_raw_response.get_logs( "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" task = await response.parse() - assert_matches_type(TaskRetrieveLogsResponse, task, path=["response"]) + assert_matches_type(TaskGetLogsResponse, task, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_streaming_response_retrieve_logs(self, async_client: AsyncBrowserUse) -> None: - async with async_client.tasks.with_streaming_response.retrieve_logs( + async def test_streaming_response_get_logs(self, async_client: AsyncBrowserUse) -> None: + async with async_client.tasks.with_streaming_response.get_logs( "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" task = await response.parse() - assert_matches_type(TaskRetrieveLogsResponse, task, path=["response"]) + assert_matches_type(TaskGetLogsResponse, task, path=["response"]) assert cast(Any, response.is_closed) is True - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_path_params_retrieve_logs(self, async_client: AsyncBrowserUse) -> None: + async def test_path_params_get_logs(self, async_client: AsyncBrowserUse) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `task_id` but received ''"): - await async_client.tasks.with_raw_response.retrieve_logs( + await async_client.tasks.with_raw_response.get_logs( "", ) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_get_output_file(self, async_client: AsyncBrowserUse) -> None: + task = await async_client.tasks.get_output_file( + file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + task_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert_matches_type(TaskGetOutputFileResponse, task, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_get_output_file(self, async_client: AsyncBrowserUse) -> None: + response = await async_client.tasks.with_raw_response.get_output_file( + file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + task_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + task = await response.parse() + assert_matches_type(TaskGetOutputFileResponse, task, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_get_output_file(self, async_client: AsyncBrowserUse) -> None: + async with async_client.tasks.with_streaming_response.get_output_file( + file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + task_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + task = await response.parse() + assert_matches_type(TaskGetOutputFileResponse, task, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_get_output_file(self, async_client: AsyncBrowserUse) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `task_id` but received ''"): + await async_client.tasks.with_raw_response.get_output_file( + file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + task_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): + await async_client.tasks.with_raw_response.get_output_file( + file_id="", + task_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_method_retrieve_output_file(self, async_client: AsyncBrowserUse) -> None: - task = await async_client.tasks.retrieve_output_file( - file_name="file_name", + async def test_method_get_user_uploaded_file(self, async_client: AsyncBrowserUse) -> None: + task = await async_client.tasks.get_user_uploaded_file( + file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", task_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) - assert_matches_type(TaskRetrieveOutputFileResponse, task, path=["response"]) + assert_matches_type(TaskGetUserUploadedFileResponse, task, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_raw_response_retrieve_output_file(self, async_client: AsyncBrowserUse) -> None: - response = await async_client.tasks.with_raw_response.retrieve_output_file( - file_name="file_name", + async def test_raw_response_get_user_uploaded_file(self, async_client: AsyncBrowserUse) -> None: + response = await async_client.tasks.with_raw_response.get_user_uploaded_file( + file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", task_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" task = await response.parse() - assert_matches_type(TaskRetrieveOutputFileResponse, task, path=["response"]) + assert_matches_type(TaskGetUserUploadedFileResponse, task, path=["response"]) - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_streaming_response_retrieve_output_file(self, async_client: AsyncBrowserUse) -> None: - async with async_client.tasks.with_streaming_response.retrieve_output_file( - file_name="file_name", + async def test_streaming_response_get_user_uploaded_file(self, async_client: AsyncBrowserUse) -> None: + async with async_client.tasks.with_streaming_response.get_user_uploaded_file( + file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", task_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" task = await response.parse() - assert_matches_type(TaskRetrieveOutputFileResponse, task, path=["response"]) + assert_matches_type(TaskGetUserUploadedFileResponse, task, path=["response"]) assert cast(Any, response.is_closed) is True - @pytest.mark.skip() + @pytest.mark.skip(reason="Prism tests are disabled") @parametrize - async def test_path_params_retrieve_output_file(self, async_client: AsyncBrowserUse) -> None: + async def test_path_params_get_user_uploaded_file(self, async_client: AsyncBrowserUse) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `task_id` but received ''"): - await async_client.tasks.with_raw_response.retrieve_output_file( - file_name="file_name", + await async_client.tasks.with_raw_response.get_user_uploaded_file( + file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", task_id="", ) - with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_name` but received ''"): - await async_client.tasks.with_raw_response.retrieve_output_file( - file_name="", + with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): + await async_client.tasks.with_raw_response.get_user_uploaded_file( + file_id="", task_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) diff --git a/src/browser_use/_version.py b/tests/api_resources/users/__init__.py similarity index 52% rename from src/browser_use/_version.py rename to tests/api_resources/users/__init__.py index 6533e52..fd8019a 100644 --- a/src/browser_use/_version.py +++ b/tests/api_resources/users/__init__.py @@ -1,4 +1 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -__title__ = "browser_use" -__version__ = "0.0.2" # x-release-please-version diff --git a/tests/api_resources/users/me/__init__.py b/tests/api_resources/users/me/__init__.py new file mode 100644 index 0000000..fd8019a --- /dev/null +++ b/tests/api_resources/users/me/__init__.py @@ -0,0 +1 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. diff --git a/tests/api_resources/users/me/test_files.py b/tests/api_resources/users/me/test_files.py new file mode 100644 index 0000000..974f05a --- /dev/null +++ b/tests/api_resources/users/me/test_files.py @@ -0,0 +1,104 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from tests.utils import assert_matches_type +from browser_use_sdk import BrowserUse, AsyncBrowserUse +from browser_use_sdk.types.users.me import FileCreatePresignedURLResponse + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestFiles: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_create_presigned_url(self, client: BrowserUse) -> None: + file = client.users.me.files.create_presigned_url( + content_type="image/jpg", + file_name="x", + size_bytes=1, + ) + assert_matches_type(FileCreatePresignedURLResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_create_presigned_url(self, client: BrowserUse) -> None: + response = client.users.me.files.with_raw_response.create_presigned_url( + content_type="image/jpg", + file_name="x", + size_bytes=1, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + file = response.parse() + assert_matches_type(FileCreatePresignedURLResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_create_presigned_url(self, client: BrowserUse) -> None: + with client.users.me.files.with_streaming_response.create_presigned_url( + content_type="image/jpg", + file_name="x", + size_bytes=1, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + file = response.parse() + assert_matches_type(FileCreatePresignedURLResponse, file, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncFiles: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_create_presigned_url(self, async_client: AsyncBrowserUse) -> None: + file = await async_client.users.me.files.create_presigned_url( + content_type="image/jpg", + file_name="x", + size_bytes=1, + ) + assert_matches_type(FileCreatePresignedURLResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_create_presigned_url(self, async_client: AsyncBrowserUse) -> None: + response = await async_client.users.me.files.with_raw_response.create_presigned_url( + content_type="image/jpg", + file_name="x", + size_bytes=1, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + file = await response.parse() + assert_matches_type(FileCreatePresignedURLResponse, file, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_create_presigned_url(self, async_client: AsyncBrowserUse) -> None: + async with async_client.users.me.files.with_streaming_response.create_presigned_url( + content_type="image/jpg", + file_name="x", + size_bytes=1, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + file = await response.parse() + assert_matches_type(FileCreatePresignedURLResponse, file, path=["response"]) + + assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/users/test_me.py b/tests/api_resources/users/test_me.py new file mode 100644 index 0000000..20e7981 --- /dev/null +++ b/tests/api_resources/users/test_me.py @@ -0,0 +1,80 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from tests.utils import assert_matches_type +from browser_use_sdk import BrowserUse, AsyncBrowserUse +from browser_use_sdk.types.users import MeRetrieveResponse + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestMe: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_retrieve(self, client: BrowserUse) -> None: + me = client.users.me.retrieve() + assert_matches_type(MeRetrieveResponse, me, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_retrieve(self, client: BrowserUse) -> None: + response = client.users.me.with_raw_response.retrieve() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + me = response.parse() + assert_matches_type(MeRetrieveResponse, me, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_retrieve(self, client: BrowserUse) -> None: + with client.users.me.with_streaming_response.retrieve() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + me = response.parse() + assert_matches_type(MeRetrieveResponse, me, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncMe: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_retrieve(self, async_client: AsyncBrowserUse) -> None: + me = await async_client.users.me.retrieve() + assert_matches_type(MeRetrieveResponse, me, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_retrieve(self, async_client: AsyncBrowserUse) -> None: + response = await async_client.users.me.with_raw_response.retrieve() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + me = await response.parse() + assert_matches_type(MeRetrieveResponse, me, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_retrieve(self, async_client: AsyncBrowserUse) -> None: + async with async_client.users.me.with_streaming_response.retrieve() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + me = await response.parse() + assert_matches_type(MeRetrieveResponse, me, path=["response"]) + + assert cast(Any, response.is_closed) is True diff --git a/tests/conftest.py b/tests/conftest.py index 17f88d9..ef9cc12 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -10,15 +10,15 @@ import pytest from pytest_asyncio import is_async_test -from browser_use import BrowserUse, AsyncBrowserUse, DefaultAioHttpClient -from browser_use._utils import is_dict +from browser_use_sdk import BrowserUse, AsyncBrowserUse, DefaultAioHttpClient +from browser_use_sdk._utils import is_dict if TYPE_CHECKING: from _pytest.fixtures import FixtureRequest # pyright: ignore[reportPrivateImportUsage] pytest.register_assert_rewrite("tests.utils") -logging.getLogger("browser_use").setLevel(logging.DEBUG) +logging.getLogger("browser_use_sdk").setLevel(logging.DEBUG) # automatically add `pytest.mark.asyncio()` to all of our async tests diff --git a/tests/test_client.py b/tests/test_client.py index 61d73bd..8f044e4 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -21,11 +21,11 @@ from respx import MockRouter from pydantic import ValidationError -from browser_use import BrowserUse, AsyncBrowserUse, APIResponseValidationError -from browser_use._types import Omit -from browser_use._models import BaseModel, FinalRequestOptions -from browser_use._exceptions import APIStatusError, APITimeoutError, BrowserUseError, APIResponseValidationError -from browser_use._base_client import ( +from browser_use_sdk import BrowserUse, AsyncBrowserUse, APIResponseValidationError +from browser_use_sdk._types import Omit +from browser_use_sdk._models import BaseModel, FinalRequestOptions +from browser_use_sdk._exceptions import APIStatusError, APITimeoutError, BrowserUseError, APIResponseValidationError +from browser_use_sdk._base_client import ( DEFAULT_TIMEOUT, HTTPX_DEFAULT_TIMEOUT, BaseClient, @@ -232,10 +232,10 @@ def add_leak(leaks: list[tracemalloc.StatisticDiff], diff: tracemalloc.Statistic # to_raw_response_wrapper leaks through the @functools.wraps() decorator. # # removing the decorator fixes the leak for reasons we don't understand. - "browser_use/_legacy_response.py", - "browser_use/_response.py", + "browser_use_sdk/_legacy_response.py", + "browser_use_sdk/_response.py", # pydantic.BaseModel.model_dump || pydantic.BaseModel.dict leak memory for some reason. - "browser_use/_compat.py", + "browser_use_sdk/_compat.py", # Standard library leaks we don't care about. "/logging/__init__.py", ] @@ -719,27 +719,27 @@ def test_parse_retry_after_header(self, remaining_retries: int, retry_after: str calculated = client._calculate_retry_timeout(remaining_retries, options, headers) assert calculated == pytest.approx(timeout, 0.5 * 0.875) # pyright: ignore[reportUnknownMemberType] - @mock.patch("browser_use._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) + @mock.patch("browser_use_sdk._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter, client: BrowserUse) -> None: - respx_mock.get("/tasks").mock(side_effect=httpx.TimeoutException("Test timeout error")) + respx_mock.get("/users/me").mock(side_effect=httpx.TimeoutException("Test timeout error")) with pytest.raises(APITimeoutError): - client.tasks.with_streaming_response.list().__enter__() + client.users.me.with_streaming_response.retrieve().__enter__() assert _get_open_connections(self.client) == 0 - @mock.patch("browser_use._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) + @mock.patch("browser_use_sdk._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter, client: BrowserUse) -> None: - respx_mock.get("/tasks").mock(return_value=httpx.Response(500)) + respx_mock.get("/users/me").mock(return_value=httpx.Response(500)) with pytest.raises(APIStatusError): - client.tasks.with_streaming_response.list().__enter__() + client.users.me.with_streaming_response.retrieve().__enter__() assert _get_open_connections(self.client) == 0 @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) - @mock.patch("browser_use._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) + @mock.patch("browser_use_sdk._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) @pytest.mark.parametrize("failure_mode", ["status", "exception"]) def test_retries_taken( @@ -762,15 +762,15 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: return httpx.Response(500) return httpx.Response(200) - respx_mock.get("/tasks").mock(side_effect=retry_handler) + respx_mock.get("/users/me").mock(side_effect=retry_handler) - response = client.tasks.with_raw_response.list() + response = client.users.me.with_raw_response.retrieve() assert response.retries_taken == failures_before_success assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) - @mock.patch("browser_use._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) + @mock.patch("browser_use_sdk._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) def test_omit_retry_count_header( self, client: BrowserUse, failures_before_success: int, respx_mock: MockRouter @@ -786,14 +786,14 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: return httpx.Response(500) return httpx.Response(200) - respx_mock.get("/tasks").mock(side_effect=retry_handler) + respx_mock.get("/users/me").mock(side_effect=retry_handler) - response = client.tasks.with_raw_response.list(extra_headers={"x-stainless-retry-count": Omit()}) + response = client.users.me.with_raw_response.retrieve(extra_headers={"x-stainless-retry-count": Omit()}) assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0 @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) - @mock.patch("browser_use._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) + @mock.patch("browser_use_sdk._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) def test_overwrite_retry_count_header( self, client: BrowserUse, failures_before_success: int, respx_mock: MockRouter @@ -809,9 +809,9 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: return httpx.Response(500) return httpx.Response(200) - respx_mock.get("/tasks").mock(side_effect=retry_handler) + respx_mock.get("/users/me").mock(side_effect=retry_handler) - response = client.tasks.with_raw_response.list(extra_headers={"x-stainless-retry-count": "42"}) + response = client.users.me.with_raw_response.retrieve(extra_headers={"x-stainless-retry-count": "42"}) assert response.http_request.headers.get("x-stainless-retry-count") == "42" @@ -1041,10 +1041,10 @@ def add_leak(leaks: list[tracemalloc.StatisticDiff], diff: tracemalloc.Statistic # to_raw_response_wrapper leaks through the @functools.wraps() decorator. # # removing the decorator fixes the leak for reasons we don't understand. - "browser_use/_legacy_response.py", - "browser_use/_response.py", + "browser_use_sdk/_legacy_response.py", + "browser_use_sdk/_response.py", # pydantic.BaseModel.model_dump || pydantic.BaseModel.dict leak memory for some reason. - "browser_use/_compat.py", + "browser_use_sdk/_compat.py", # Standard library leaks we don't care about. "/logging/__init__.py", ] @@ -1534,31 +1534,31 @@ async def test_parse_retry_after_header(self, remaining_retries: int, retry_afte calculated = client._calculate_retry_timeout(remaining_retries, options, headers) assert calculated == pytest.approx(timeout, 0.5 * 0.875) # pyright: ignore[reportUnknownMemberType] - @mock.patch("browser_use._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) + @mock.patch("browser_use_sdk._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) async def test_retrying_timeout_errors_doesnt_leak( self, respx_mock: MockRouter, async_client: AsyncBrowserUse ) -> None: - respx_mock.get("/tasks").mock(side_effect=httpx.TimeoutException("Test timeout error")) + respx_mock.get("/users/me").mock(side_effect=httpx.TimeoutException("Test timeout error")) with pytest.raises(APITimeoutError): - await async_client.tasks.with_streaming_response.list().__aenter__() + await async_client.users.me.with_streaming_response.retrieve().__aenter__() assert _get_open_connections(self.client) == 0 - @mock.patch("browser_use._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) + @mock.patch("browser_use_sdk._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) async def test_retrying_status_errors_doesnt_leak( self, respx_mock: MockRouter, async_client: AsyncBrowserUse ) -> None: - respx_mock.get("/tasks").mock(return_value=httpx.Response(500)) + respx_mock.get("/users/me").mock(return_value=httpx.Response(500)) with pytest.raises(APIStatusError): - await async_client.tasks.with_streaming_response.list().__aenter__() + await async_client.users.me.with_streaming_response.retrieve().__aenter__() assert _get_open_connections(self.client) == 0 @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) - @mock.patch("browser_use._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) + @mock.patch("browser_use_sdk._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) @pytest.mark.asyncio @pytest.mark.parametrize("failure_mode", ["status", "exception"]) @@ -1582,15 +1582,15 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: return httpx.Response(500) return httpx.Response(200) - respx_mock.get("/tasks").mock(side_effect=retry_handler) + respx_mock.get("/users/me").mock(side_effect=retry_handler) - response = await client.tasks.with_raw_response.list() + response = await client.users.me.with_raw_response.retrieve() assert response.retries_taken == failures_before_success assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) - @mock.patch("browser_use._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) + @mock.patch("browser_use_sdk._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) @pytest.mark.asyncio async def test_omit_retry_count_header( @@ -1607,14 +1607,14 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: return httpx.Response(500) return httpx.Response(200) - respx_mock.get("/tasks").mock(side_effect=retry_handler) + respx_mock.get("/users/me").mock(side_effect=retry_handler) - response = await client.tasks.with_raw_response.list(extra_headers={"x-stainless-retry-count": Omit()}) + response = await client.users.me.with_raw_response.retrieve(extra_headers={"x-stainless-retry-count": Omit()}) assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0 @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) - @mock.patch("browser_use._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) + @mock.patch("browser_use_sdk._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) @pytest.mark.asyncio async def test_overwrite_retry_count_header( @@ -1631,9 +1631,9 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: return httpx.Response(500) return httpx.Response(200) - respx_mock.get("/tasks").mock(side_effect=retry_handler) + respx_mock.get("/users/me").mock(side_effect=retry_handler) - response = await client.tasks.with_raw_response.list(extra_headers={"x-stainless-retry-count": "42"}) + response = await client.users.me.with_raw_response.retrieve(extra_headers={"x-stainless-retry-count": "42"}) assert response.http_request.headers.get("x-stainless-retry-count") == "42" @@ -1648,8 +1648,8 @@ def test_get_platform(self) -> None: import nest_asyncio import threading - from browser_use._utils import asyncify - from browser_use._base_client import get_platform + from browser_use_sdk._utils import asyncify + from browser_use_sdk._base_client import get_platform async def test_main() -> None: result = await asyncify(get_platform)() diff --git a/tests/test_deepcopy.py b/tests/test_deepcopy.py index fb58ebe..852adc3 100644 --- a/tests/test_deepcopy.py +++ b/tests/test_deepcopy.py @@ -1,4 +1,4 @@ -from browser_use._utils import deepcopy_minimal +from browser_use_sdk._utils import deepcopy_minimal def assert_different_identities(obj1: object, obj2: object) -> None: diff --git a/tests/test_extract_files.py b/tests/test_extract_files.py index da97c73..151f6c6 100644 --- a/tests/test_extract_files.py +++ b/tests/test_extract_files.py @@ -4,8 +4,8 @@ import pytest -from browser_use._types import FileTypes -from browser_use._utils import extract_files +from browser_use_sdk._types import FileTypes +from browser_use_sdk._utils import extract_files def test_removes_files_from_input() -> None: diff --git a/tests/test_files.py b/tests/test_files.py index 661756f..f14804f 100644 --- a/tests/test_files.py +++ b/tests/test_files.py @@ -4,7 +4,7 @@ import pytest from dirty_equals import IsDict, IsList, IsBytes, IsTuple -from browser_use._files import to_httpx_files, async_to_httpx_files +from browser_use_sdk._files import to_httpx_files, async_to_httpx_files readme_path = Path(__file__).parent.parent.joinpath("README.md") diff --git a/tests/test_models.py b/tests/test_models.py index 72d4485..ee8ad87 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -7,9 +7,9 @@ import pydantic from pydantic import Field -from browser_use._utils import PropertyInfo -from browser_use._compat import PYDANTIC_V2, parse_obj, model_dump, model_json -from browser_use._models import BaseModel, construct_type +from browser_use_sdk._utils import PropertyInfo +from browser_use_sdk._compat import PYDANTIC_V2, parse_obj, model_dump, model_json +from browser_use_sdk._models import BaseModel, construct_type class BasicModel(BaseModel): diff --git a/tests/test_qs.py b/tests/test_qs.py index c45435d..b47f757 100644 --- a/tests/test_qs.py +++ b/tests/test_qs.py @@ -4,7 +4,7 @@ import pytest -from browser_use._qs import Querystring, stringify +from browser_use_sdk._qs import Querystring, stringify def test_empty() -> None: diff --git a/tests/test_required_args.py b/tests/test_required_args.py index dda707d..eb5821a 100644 --- a/tests/test_required_args.py +++ b/tests/test_required_args.py @@ -2,7 +2,7 @@ import pytest -from browser_use._utils import required_args +from browser_use_sdk._utils import required_args def test_too_many_positional_params() -> None: diff --git a/tests/test_response.py b/tests/test_response.py index 97cf7da..c64b9ed 100644 --- a/tests/test_response.py +++ b/tests/test_response.py @@ -6,8 +6,8 @@ import pytest import pydantic -from browser_use import BaseModel, BrowserUse, AsyncBrowserUse -from browser_use._response import ( +from browser_use_sdk import BaseModel, BrowserUse, AsyncBrowserUse +from browser_use_sdk._response import ( APIResponse, BaseAPIResponse, AsyncAPIResponse, @@ -15,8 +15,8 @@ AsyncBinaryAPIResponse, extract_response_type, ) -from browser_use._streaming import Stream -from browser_use._base_client import FinalRequestOptions +from browser_use_sdk._streaming import Stream +from browser_use_sdk._base_client import FinalRequestOptions class ConcreteBaseAPIResponse(APIResponse[bytes]): ... @@ -37,7 +37,7 @@ def test_extract_response_type_direct_classes() -> None: def test_extract_response_type_direct_class_missing_type_arg() -> None: with pytest.raises( RuntimeError, - match="Expected type to have a type argument at index 0 but it did not", + match="Expected type to have a type argument at index 0 but it did not", ): extract_response_type(AsyncAPIResponse) @@ -68,7 +68,7 @@ def test_response_parse_mismatched_basemodel(client: BrowserUse) -> None: with pytest.raises( TypeError, - match="Pydantic models must subclass our base model type, e.g. `from browser_use import BaseModel`", + match="Pydantic models must subclass our base model type, e.g. `from browser_use_sdk import BaseModel`", ): response.parse(to=PydanticModel) @@ -86,7 +86,7 @@ async def test_async_response_parse_mismatched_basemodel(async_client: AsyncBrow with pytest.raises( TypeError, - match="Pydantic models must subclass our base model type, e.g. `from browser_use import BaseModel`", + match="Pydantic models must subclass our base model type, e.g. `from browser_use_sdk import BaseModel`", ): await response.parse(to=PydanticModel) diff --git a/tests/test_streaming.py b/tests/test_streaming.py index 73fb1c3..84f2452 100644 --- a/tests/test_streaming.py +++ b/tests/test_streaming.py @@ -5,8 +5,8 @@ import httpx import pytest -from browser_use import BrowserUse, AsyncBrowserUse -from browser_use._streaming import Stream, AsyncStream, ServerSentEvent +from browser_use_sdk import BrowserUse, AsyncBrowserUse +from browser_use_sdk._streaming import Stream, AsyncStream, ServerSentEvent @pytest.mark.asyncio diff --git a/tests/test_transform.py b/tests/test_transform.py index 89aa594..b336597 100644 --- a/tests/test_transform.py +++ b/tests/test_transform.py @@ -8,15 +8,15 @@ import pytest -from browser_use._types import NOT_GIVEN, Base64FileInput -from browser_use._utils import ( +from browser_use_sdk._types import NOT_GIVEN, Base64FileInput +from browser_use_sdk._utils import ( PropertyInfo, transform as _transform, parse_datetime, async_transform as _async_transform, ) -from browser_use._compat import PYDANTIC_V2 -from browser_use._models import BaseModel +from browser_use_sdk._compat import PYDANTIC_V2 +from browser_use_sdk._models import BaseModel _T = TypeVar("_T") diff --git a/tests/test_utils/test_proxy.py b/tests/test_utils/test_proxy.py index 50e1b43..a76d3a9 100644 --- a/tests/test_utils/test_proxy.py +++ b/tests/test_utils/test_proxy.py @@ -2,7 +2,7 @@ from typing import Any from typing_extensions import override -from browser_use._utils import LazyProxy +from browser_use_sdk._utils import LazyProxy class RecursiveLazyProxy(LazyProxy[Any]): diff --git a/tests/test_utils/test_typing.py b/tests/test_utils/test_typing.py index b329aab..e12cde1 100644 --- a/tests/test_utils/test_typing.py +++ b/tests/test_utils/test_typing.py @@ -2,7 +2,7 @@ from typing import Generic, TypeVar, cast -from browser_use._utils import extract_type_var_from_base +from browser_use_sdk._utils import extract_type_var_from_base _T = TypeVar("_T") _T2 = TypeVar("_T2") diff --git a/tests/utils.py b/tests/utils.py index 2a8ebf0..858cc96 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -8,8 +8,8 @@ from datetime import date, datetime from typing_extensions import Literal, get_args, get_origin, assert_type -from browser_use._types import Omit, NoneType -from browser_use._utils import ( +from browser_use_sdk._types import Omit, NoneType +from browser_use_sdk._utils import ( is_dict, is_list, is_list_type, @@ -18,8 +18,8 @@ is_annotated_type, is_type_alias_type, ) -from browser_use._compat import PYDANTIC_V2, field_outer_type, get_model_fields -from browser_use._models import BaseModel +from browser_use_sdk._compat import PYDANTIC_V2, field_outer_type, get_model_fields +from browser_use_sdk._models import BaseModel BaseModelT = TypeVar("BaseModelT", bound=BaseModel)