From 255dba1ceba79080376241f25614fc2a378152df Mon Sep 17 00:00:00 2001 From: fern-api <115122769+fern-api[bot]@users.noreply.github.com> Date: Wed, 26 Feb 2025 02:52:02 +0000 Subject: [PATCH 1/4] SDK regeneration --- poetry.lock | 6 +- pyproject.toml | 2 +- reference.md | 73 +++++++++ src/scrapybara/__init__.py | 2 + src/scrapybara/browser/client.py | 149 ++++++++++++++++++ src/scrapybara/core/client_wrapper.py | 20 +-- src/scrapybara/herd/__init__.py | 19 --- .../types/modify_browser_auth_response.py | 21 +++ src/scrapybara/types/status.py | 2 +- 9 files changed, 254 insertions(+), 40 deletions(-) delete mode 100644 src/scrapybara/herd/__init__.py create mode 100644 src/scrapybara/types/modify_browser_auth_response.py diff --git a/poetry.lock b/poetry.lock index 8c03bbe..d4aec81 100644 --- a/poetry.lock +++ b/poetry.lock @@ -62,13 +62,13 @@ trio = ["trio (>=0.26.1)"] [[package]] name = "certifi" -version = "2024.12.14" +version = "2025.1.31" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2024.12.14-py3-none-any.whl", hash = "sha256:1275f7a45be9464efc1173084eaa30f866fe2e47d389406136d332ed4967ec56"}, - {file = "certifi-2024.12.14.tar.gz", hash = "sha256:b650d30f370c2b724812bee08008be0c4163b163ddaec3f2546c1caf65f191db"}, + {file = "certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe"}, + {file = "certifi-2025.1.31.tar.gz", hash = "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651"}, ] [[package]] diff --git a/pyproject.toml b/pyproject.toml index d33b015..bfbbcd6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "scrapybara" -version = "2.2.7" +version = "2.2.8" description = "" readme = "README.md" authors = [] diff --git a/reference.md b/reference.md index a16e22d..a8e0763 100644 --- a/reference.md +++ b/reference.md @@ -938,6 +938,79 @@ client.browser.save_auth( + + + + +
client.browser.modify_auth(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from scrapybara import Scrapybara + +client = Scrapybara( + api_key="YOUR_API_KEY", +) +client.browser.modify_auth( + instance_id="instance_id", + auth_state_id="auth_state_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**instance_id:** `str` + +
+
+ +
+
+ +**auth_state_id:** `str` + +
+
+ +
+
+ +**name:** `typing.Optional[str]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ +
diff --git a/src/scrapybara/__init__.py b/src/scrapybara/__init__.py index 4921e4c..5311076 100644 --- a/src/scrapybara/__init__.py +++ b/src/scrapybara/__init__.py @@ -17,6 +17,7 @@ InstanceGetStreamUrlResponse, InstanceScreenshotResponse, KernelInfo, + ModifyBrowserAuthResponse, Notebook, NotebookCell, SaveBrowserAuthResponse, @@ -54,6 +55,7 @@ "InstanceGetStreamUrlResponse", "InstanceScreenshotResponse", "KernelInfo", + "ModifyBrowserAuthResponse", "Notebook", "NotebookCell", "SaveBrowserAuthResponse", diff --git a/src/scrapybara/browser/client.py b/src/scrapybara/browser/client.py index a77c77f..b9add3c 100644 --- a/src/scrapybara/browser/client.py +++ b/src/scrapybara/browser/client.py @@ -12,6 +12,7 @@ from ..core.api_error import ApiError from ..types.browser_get_cdp_url_response import BrowserGetCdpUrlResponse from ..types.save_browser_auth_response import SaveBrowserAuthResponse +from ..types.modify_browser_auth_response import ModifyBrowserAuthResponse from ..types.browser_authenticate_response import BrowserAuthenticateResponse from ..types.stop_browser_response import StopBrowserResponse from ..core.client_wrapper import AsyncClientWrapper @@ -198,6 +199,76 @@ def save_auth( raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) + def modify_auth( + self, + instance_id: str, + *, + auth_state_id: str, + name: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> ModifyBrowserAuthResponse: + """ + Parameters + ---------- + instance_id : str + + auth_state_id : str + + name : typing.Optional[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ModifyBrowserAuthResponse + Successful Response + + Examples + -------- + from scrapybara import Scrapybara + + client = Scrapybara( + api_key="YOUR_API_KEY", + ) + client.browser.modify_auth( + instance_id="instance_id", + auth_state_id="auth_state_id", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/instance/{jsonable_encoder(instance_id)}/browser/modify_auth", + method="POST", + params={ + "auth_state_id": auth_state_id, + "name": name, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + ModifyBrowserAuthResponse, + parse_obj_as( + type_=ModifyBrowserAuthResponse, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 422: + raise UnprocessableEntityError( + typing.cast( + HttpValidationError, + parse_obj_as( + type_=HttpValidationError, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + def authenticate( self, instance_id: str, *, auth_state_id: str, request_options: typing.Optional[RequestOptions] = None ) -> BrowserAuthenticateResponse: @@ -520,6 +591,84 @@ async def main() -> None: raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) + async def modify_auth( + self, + instance_id: str, + *, + auth_state_id: str, + name: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> ModifyBrowserAuthResponse: + """ + Parameters + ---------- + instance_id : str + + auth_state_id : str + + name : typing.Optional[str] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ModifyBrowserAuthResponse + Successful Response + + Examples + -------- + import asyncio + + from scrapybara import AsyncScrapybara + + client = AsyncScrapybara( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.browser.modify_auth( + instance_id="instance_id", + auth_state_id="auth_state_id", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/instance/{jsonable_encoder(instance_id)}/browser/modify_auth", + method="POST", + params={ + "auth_state_id": auth_state_id, + "name": name, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + ModifyBrowserAuthResponse, + parse_obj_as( + type_=ModifyBrowserAuthResponse, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 422: + raise UnprocessableEntityError( + typing.cast( + HttpValidationError, + parse_obj_as( + type_=HttpValidationError, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + async def authenticate( self, instance_id: str, *, auth_state_id: str, request_options: typing.Optional[RequestOptions] = None ) -> BrowserAuthenticateResponse: diff --git a/src/scrapybara/core/client_wrapper.py b/src/scrapybara/core/client_wrapper.py index ea31b0e..4cdb0d2 100644 --- a/src/scrapybara/core/client_wrapper.py +++ b/src/scrapybara/core/client_wrapper.py @@ -7,9 +7,7 @@ class BaseClientWrapper: - def __init__( - self, *, api_key: str, base_url: str, timeout: typing.Optional[float] = None - ): + def __init__(self, *, api_key: str, base_url: str, timeout: typing.Optional[float] = None): self.api_key = api_key self._base_url = base_url self._timeout = timeout @@ -18,7 +16,7 @@ def get_headers(self) -> typing.Dict[str, str]: headers: typing.Dict[str, str] = { "X-Fern-Language": "Python", "X-Fern-SDK-Name": "scrapybara", - "X-Fern-SDK-Version": "2.2.7", + "X-Fern-SDK-Version": "2.2.8", } headers["x-api-key"] = self.api_key return headers @@ -32,12 +30,7 @@ def get_timeout(self) -> typing.Optional[float]: class SyncClientWrapper(BaseClientWrapper): def __init__( - self, - *, - api_key: str, - base_url: str, - timeout: typing.Optional[float] = None, - httpx_client: httpx.Client + self, *, api_key: str, base_url: str, timeout: typing.Optional[float] = None, httpx_client: httpx.Client ): super().__init__(api_key=api_key, base_url=base_url, timeout=timeout) self.httpx_client = HttpClient( @@ -50,12 +43,7 @@ def __init__( class AsyncClientWrapper(BaseClientWrapper): def __init__( - self, - *, - api_key: str, - base_url: str, - timeout: typing.Optional[float] = None, - httpx_client: httpx.AsyncClient + self, *, api_key: str, base_url: str, timeout: typing.Optional[float] = None, httpx_client: httpx.AsyncClient ): super().__init__(api_key=api_key, base_url=base_url, timeout=timeout) self.httpx_client = AsyncHttpClient( diff --git a/src/scrapybara/herd/__init__.py b/src/scrapybara/herd/__init__.py deleted file mode 100644 index 98190ad..0000000 --- a/src/scrapybara/herd/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -from ..types.act import Model -from typing import Literal -from pydantic import Field - - -class Herd(Model): - """Model adapter for Herd (Scrapybara-hosted LLMs). - - Args: - name: Herd model name - - Returns: - A Model configuration object - """ - - provider: Literal["herd"] = Field(default="herd", frozen=True) - - def __init__(self, name: str) -> None: - super().__init__(provider="herd", name=name) diff --git a/src/scrapybara/types/modify_browser_auth_response.py b/src/scrapybara/types/modify_browser_auth_response.py new file mode 100644 index 0000000..84fec1d --- /dev/null +++ b/src/scrapybara/types/modify_browser_auth_response.py @@ -0,0 +1,21 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class ModifyBrowserAuthResponse(UniversalBaseModel): + status: str + auth_state_id: str + name: typing.Optional[str] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/scrapybara/types/status.py b/src/scrapybara/types/status.py index bdef0a9..3fb3c9c 100644 --- a/src/scrapybara/types/status.py +++ b/src/scrapybara/types/status.py @@ -2,4 +2,4 @@ import typing -Status = typing.Union[typing.Literal["deploying", "running", "terminated", "error"], typing.Any] +Status = typing.Union[typing.Literal["deploying", "running", "paused", "terminated", "error"], typing.Any] From c7113bae9983b760b9111a6dd474909c3a65d05a Mon Sep 17 00:00:00 2001 From: Justin Sun Date: Tue, 25 Feb 2025 19:04:26 -0800 Subject: [PATCH 2/4] feat;: add modify browser auth + sonnet 3.7 --- .fernignore | 1 + src/scrapybara/anthropic/__init__.py | 6 ++++-- src/scrapybara/client.py | 29 ++++++++++++++++++++++++++++ src/scrapybara/herd/__init__.py | 19 ++++++++++++++++++ src/scrapybara/types/__init__.py | 2 ++ 5 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 src/scrapybara/herd/__init__.py diff --git a/.fernignore b/.fernignore index e666a72..3eb9c64 100644 --- a/.fernignore +++ b/.fernignore @@ -2,6 +2,7 @@ src/scrapybara/client.py src/scrapybara/anthropic/ +src/scrapybara/herd/ src/scrapybara/prompts/ src/scrapybara/tools/ src/scrapybara/types/__init__.py diff --git a/src/scrapybara/anthropic/__init__.py b/src/scrapybara/anthropic/__init__.py index f5cdafd..847c4d1 100644 --- a/src/scrapybara/anthropic/__init__.py +++ b/src/scrapybara/anthropic/__init__.py @@ -17,10 +17,12 @@ class Anthropic(Model): """Model adapter for Anthropic. Supported models: + - claude-3-7-sonnet-20250219 (1x agent credit if no api_key) + - claude-3-7-sonnet-20250219-thinking (1x agent credit if no api_key) - claude-3-5-sonnet-20241022 (1x agent credit if no api_key) Args: - name: Anthropic model name, defaults to "claude-3-5-sonnet-20241022" + name: Anthropic model name, defaults to "claude-3-7-sonnet-20250219" api_key: Optional Anthropic API key Returns: @@ -31,7 +33,7 @@ class Anthropic(Model): def __init__( self, - name: Optional[str] = "claude-3-5-sonnet-20241022", + name: Optional[str] = "claude-3-7-sonnet-20250219", api_key: Optional[str] = None, ) -> None: super().__init__(provider="anthropic", name=name, api_key=api_key) diff --git a/src/scrapybara/client.py b/src/scrapybara/client.py index 5b277aa..748a29f 100644 --- a/src/scrapybara/client.py +++ b/src/scrapybara/client.py @@ -43,6 +43,7 @@ StartBrowserResponse, StopBrowserResponse, StopInstanceResponse, + ModifyBrowserAuthResponse, ) from .types.act import ( SingleActRequest, @@ -116,6 +117,20 @@ def save_auth( self.instance_id, name=name, request_options=request_options ) + def modify_auth( + self, + *, + auth_state_id: str, + name: Optional[str] = None, + request_options: Optional[RequestOptions] = None, + ) -> ModifyBrowserAuthResponse: + return self._client.browser.modify_auth( + self.instance_id, + auth_state_id=auth_state_id, + name=name, + request_options=request_options, + ) + def authenticate( self, *, auth_state_id: str, request_options: Optional[RequestOptions] = None ) -> BrowserAuthenticateResponse: @@ -162,6 +177,20 @@ async def save_auth( self.instance_id, name=name, request_options=request_options ) + async def modify_auth( + self, + *, + auth_state_id: str, + name: Optional[str] = None, + request_options: Optional[RequestOptions] = None, + ) -> ModifyBrowserAuthResponse: + return await self._client.browser.modify_auth( + self.instance_id, + auth_state_id=auth_state_id, + name=name, + request_options=request_options, + ) + async def authenticate( self, *, auth_state_id: str, request_options: Optional[RequestOptions] = None ) -> BrowserAuthenticateResponse: diff --git a/src/scrapybara/herd/__init__.py b/src/scrapybara/herd/__init__.py new file mode 100644 index 0000000..98190ad --- /dev/null +++ b/src/scrapybara/herd/__init__.py @@ -0,0 +1,19 @@ +from ..types.act import Model +from typing import Literal +from pydantic import Field + + +class Herd(Model): + """Model adapter for Herd (Scrapybara-hosted LLMs). + + Args: + name: Herd model name + + Returns: + A Model configuration object + """ + + provider: Literal["herd"] = Field(default="herd", frozen=True) + + def __init__(self, name: str) -> None: + super().__init__(provider="herd", name=name) diff --git a/src/scrapybara/types/__init__.py b/src/scrapybara/types/__init__.py index 5c318a2..59c6a92 100644 --- a/src/scrapybara/types/__init__.py +++ b/src/scrapybara/types/__init__.py @@ -14,6 +14,7 @@ from .instance_get_stream_url_response import InstanceGetStreamUrlResponse from .instance_screenshot_response import InstanceScreenshotResponse from .kernel_info import KernelInfo +from .modify_browser_auth_response import ModifyBrowserAuthResponse from .notebook import Notebook from .notebook_cell import NotebookCell from .save_browser_auth_response import SaveBrowserAuthResponse @@ -58,6 +59,7 @@ "InstanceGetStreamUrlResponse", "InstanceScreenshotResponse", "KernelInfo", + "ModifyBrowserAuthResponse", "Notebook", "NotebookCell", "SaveBrowserAuthResponse", From 86c2f9696fde25aa7f88e77b0a3e62052b7fed65 Mon Sep 17 00:00:00 2001 From: Justin Sun Date: Tue, 25 Feb 2025 19:28:11 -0800 Subject: [PATCH 3/4] feat: add modify_auth to browser instances --- src/scrapybara/client.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/scrapybara/client.py b/src/scrapybara/client.py index 748a29f..78f6bc8 100644 --- a/src/scrapybara/client.py +++ b/src/scrapybara/client.py @@ -744,6 +744,20 @@ def save_auth( self.id, name=name, request_options=request_options ) + def modify_auth( + self, + *, + auth_state_id: str, + name: Optional[str] = None, + request_options: Optional[RequestOptions] = None, + ) -> ModifyBrowserAuthResponse: + return self._client.browser.modify_auth( + self.id, + auth_state_id=auth_state_id, + name=name, + request_options=request_options, + ) + def authenticate( self, *, auth_state_id: str, request_options: Optional[RequestOptions] = None ) -> BrowserAuthenticateResponse: @@ -913,6 +927,20 @@ async def save_auth( self.id, name=name, request_options=request_options ) + async def modify_auth( + self, + *, + auth_state_id: str, + name: Optional[str] = None, + request_options: Optional[RequestOptions] = None, + ) -> ModifyBrowserAuthResponse: + return await self._client.browser.modify_auth( + self.id, + auth_state_id=auth_state_id, + name=name, + request_options=request_options, + ) + async def authenticate( self, *, auth_state_id: str, request_options: Optional[RequestOptions] = None ) -> BrowserAuthenticateResponse: From 09fce241e1a987a58da46c4495dca83f231e846d Mon Sep 17 00:00:00 2001 From: Justin Sun Date: Tue, 25 Feb 2025 19:34:47 -0800 Subject: [PATCH 4/4] chore: update anthropic SDK --- poetry.lock | 12 ++++++------ pyproject.toml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/poetry.lock b/poetry.lock index d4aec81..3ce8f58 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.4 and should not be changed by hand. [[package]] name = "annotated-types" @@ -16,13 +16,13 @@ typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.9\""} [[package]] name = "anthropic" -version = "0.39.0" +version = "0.47.2" description = "The official Python library for the anthropic API" optional = false python-versions = ">=3.8" files = [ - {file = "anthropic-0.39.0-py3-none-any.whl", hash = "sha256:ea17093ae0ce0e1768b0c46501d6086b5bcd74ff39d68cd2d6396374e9de7c09"}, - {file = "anthropic-0.39.0.tar.gz", hash = "sha256:94671cc80765f9ce693f76d63a97ee9bef4c2d6063c044e983d21a2e262f63ba"}, + {file = "anthropic-0.47.2-py3-none-any.whl", hash = "sha256:61b712a56308fce69f04d92ba0230ab2bc187b5bce17811d400843a8976bb67f"}, + {file = "anthropic-0.47.2.tar.gz", hash = "sha256:452f4ca0c56ffab8b6ce9928bf8470650f88106a7001b250895eb65c54cfa44c"}, ] [package.dependencies] @@ -32,7 +32,7 @@ httpx = ">=0.23.0,<1" jiter = ">=0.4.0,<1" pydantic = ">=1.9.0,<3" sniffio = "*" -typing-extensions = ">=4.7,<5" +typing-extensions = ">=4.10,<5" [package.extras] bedrock = ["boto3 (>=1.28.57)", "botocore (>=1.31.57)"] @@ -780,4 +780,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "8130552a641501ad4537fd8c8eec56deb0b111b9da63b6460974bd12d106ff5a" +content-hash = "afd12abd07590f9897eb7e414c5b497477e5fd6e31bfb4390cac050339717ccd" diff --git a/pyproject.toml b/pyproject.toml index bfbbcd6..32fd0ae 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,7 +32,7 @@ Repository = 'https://github.com/scrapybara/scrapybara-python' [tool.poetry.dependencies] python = "^3.8" -anthropic = "^0.39.0" +anthropic = "^0.47.2" httpx = ">=0.21.2" playwright = "^1.48.0" pydantic = ">= 1.9.2"