diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index a26ebfc1..54c4d98a 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.14.0"
+ ".": "0.14.1"
}
\ No newline at end of file
diff --git a/.stats.yml b/.stats.yml
index f577dd04..99609550 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 57
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-936db268b3dcae5d64bd5d590506d8134304ffcbf67389eb9b1555b3febfd4cb.yml
-openapi_spec_hash: 145485087adf1b28c052bacb4df68462
-config_hash: 15cd063f8e308686ac71bf9ee9634625
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-1cd328ccf61f0e888d6df27b091c30b38c392ab9ca8ce7fd0ead8f10aaf71ffa.yml
+openapi_spec_hash: af761c48d1955f11822f3b95f9c46750
+config_hash: deadfc4d2b0a947673bcf559b5db6e1b
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 60ce7eee..c32e5660 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,19 @@
# Changelog
+## 0.14.1 (2025-10-13)
+
+Full Changelog: [v0.14.0...v0.14.1](https://github.com/onkernel/kernel-python-sdk/compare/v0.14.0...v0.14.1)
+
+### Features
+
+* Hide and deprecate mobile proxy type ([bee8d86](https://github.com/onkernel/kernel-python-sdk/commit/bee8d86588ce57de073583fa7e94a5ba38f21b9a))
+* WIP: Configurable Viewport ([60b9961](https://github.com/onkernel/kernel-python-sdk/commit/60b99616dea9fa4ba823f58c2c18ea9dda60b836))
+
+
+### Chores
+
+* **internal:** detect missing future annotations with ruff ([b53927c](https://github.com/onkernel/kernel-python-sdk/commit/b53927c4013a34ad6afee95efe5608b56e34755a))
+
## 0.14.0 (2025-10-07)
Full Changelog: [v0.13.0...v0.14.0](https://github.com/onkernel/kernel-python-sdk/compare/v0.13.0...v0.14.0)
diff --git a/api.md b/api.md
index be7fff4e..6059a78d 100644
--- a/api.md
+++ b/api.md
@@ -82,7 +82,7 @@ Methods:
- client.browsers.list() -> BrowserListResponse
- client.browsers.delete(\*\*params) -> None
- client.browsers.delete_by_id(id) -> None
-- client.browsers.upload_extensions(id, \*\*params) -> None
+- client.browsers.load_extensions(id, \*\*params) -> None
## Replays
diff --git a/pyproject.toml b/pyproject.toml
index 3219e080..f3f78745 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "kernel"
-version = "0.14.0"
+version = "0.14.1"
description = "The official Python library for the kernel API"
dynamic = ["readme"]
license = "Apache-2.0"
@@ -224,6 +224,8 @@ select = [
"B",
# remove unused imports
"F401",
+ # check for missing future annotations
+ "FA102",
# bare except statements
"E722",
# unused arguments
@@ -246,6 +248,8 @@ unfixable = [
"T203",
]
+extend-safe-fixes = ["FA102"]
+
[tool.ruff.lint.flake8-tidy-imports.banned-api]
"functools.lru_cache".msg = "This function does not retain type information for the wrapped function's arguments; The `lru_cache` function from `_utils` should be used instead"
diff --git a/src/kernel/_version.py b/src/kernel/_version.py
index 0bebaf17..365119e9 100644
--- a/src/kernel/_version.py
+++ b/src/kernel/_version.py
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
__title__ = "kernel"
-__version__ = "0.14.0" # x-release-please-version
+__version__ = "0.14.1" # x-release-please-version
diff --git a/src/kernel/resources/browsers/browsers.py b/src/kernel/resources/browsers/browsers.py
index 5e5530b1..3e3eb8df 100644
--- a/src/kernel/resources/browsers/browsers.py
+++ b/src/kernel/resources/browsers/browsers.py
@@ -22,7 +22,7 @@
FsResourceWithStreamingResponse,
AsyncFsResourceWithStreamingResponse,
)
-from ...types import browser_create_params, browser_delete_params, browser_upload_extensions_params
+from ...types import browser_create_params, browser_delete_params, browser_load_extensions_params
from .process import (
ProcessResource,
AsyncProcessResource,
@@ -105,6 +105,7 @@ def create(
proxy_id: str | Omit = omit,
stealth: bool | Omit = omit,
timeout_seconds: int | Omit = omit,
+ viewport: browser_create_params.Viewport | Omit = omit,
# 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,
@@ -142,6 +143,15 @@ def create(
seconds, so the actual timeout behavior you will see is +/- 5 seconds around the
specified value.
+ viewport: Initial browser window size in pixels with optional refresh rate. If omitted,
+ image defaults apply (commonly 1024x768@60). Only specific viewport
+ configurations are supported. The server will reject unsupported combinations.
+ Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25,
+ 1440x900@25, 1024x768@60 If refresh_rate is not provided, it will be
+ automatically determined from the width and height if they match a supported
+ configuration exactly. Note: Higher resolutions may affect the responsiveness of
+ live view browser
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -162,6 +172,7 @@ def create(
"proxy_id": proxy_id,
"stealth": stealth,
"timeout_seconds": timeout_seconds,
+ "viewport": viewport,
},
browser_create_params.BrowserCreateParams,
),
@@ -295,11 +306,11 @@ def delete_by_id(
cast_to=NoneType,
)
- def upload_extensions(
+ def load_extensions(
self,
id: str,
*,
- extensions: Iterable[browser_upload_extensions_params.Extension],
+ extensions: Iterable[browser_load_extensions_params.Extension],
# 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,
@@ -333,7 +344,7 @@ def upload_extensions(
extra_headers["Content-Type"] = "multipart/form-data"
return self._post(
f"/browsers/{id}/extensions",
- body=maybe_transform(body, browser_upload_extensions_params.BrowserUploadExtensionsParams),
+ body=maybe_transform(body, browser_load_extensions_params.BrowserLoadExtensionsParams),
files=files,
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
@@ -389,6 +400,7 @@ async def create(
proxy_id: str | Omit = omit,
stealth: bool | Omit = omit,
timeout_seconds: int | Omit = omit,
+ viewport: browser_create_params.Viewport | Omit = omit,
# 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,
@@ -426,6 +438,15 @@ async def create(
seconds, so the actual timeout behavior you will see is +/- 5 seconds around the
specified value.
+ viewport: Initial browser window size in pixels with optional refresh rate. If omitted,
+ image defaults apply (commonly 1024x768@60). Only specific viewport
+ configurations are supported. The server will reject unsupported combinations.
+ Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25,
+ 1440x900@25, 1024x768@60 If refresh_rate is not provided, it will be
+ automatically determined from the width and height if they match a supported
+ configuration exactly. Note: Higher resolutions may affect the responsiveness of
+ live view browser
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -446,6 +467,7 @@ async def create(
"proxy_id": proxy_id,
"stealth": stealth,
"timeout_seconds": timeout_seconds,
+ "viewport": viewport,
},
browser_create_params.BrowserCreateParams,
),
@@ -581,11 +603,11 @@ async def delete_by_id(
cast_to=NoneType,
)
- async def upload_extensions(
+ async def load_extensions(
self,
id: str,
*,
- extensions: Iterable[browser_upload_extensions_params.Extension],
+ extensions: Iterable[browser_load_extensions_params.Extension],
# 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,
@@ -619,7 +641,7 @@ async def upload_extensions(
extra_headers["Content-Type"] = "multipart/form-data"
return await self._post(
f"/browsers/{id}/extensions",
- body=await async_maybe_transform(body, browser_upload_extensions_params.BrowserUploadExtensionsParams),
+ body=await async_maybe_transform(body, browser_load_extensions_params.BrowserLoadExtensionsParams),
files=files,
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
@@ -647,8 +669,8 @@ def __init__(self, browsers: BrowsersResource) -> None:
self.delete_by_id = to_raw_response_wrapper(
browsers.delete_by_id,
)
- self.upload_extensions = to_raw_response_wrapper(
- browsers.upload_extensions,
+ self.load_extensions = to_raw_response_wrapper(
+ browsers.load_extensions,
)
@cached_property
@@ -687,8 +709,8 @@ def __init__(self, browsers: AsyncBrowsersResource) -> None:
self.delete_by_id = async_to_raw_response_wrapper(
browsers.delete_by_id,
)
- self.upload_extensions = async_to_raw_response_wrapper(
- browsers.upload_extensions,
+ self.load_extensions = async_to_raw_response_wrapper(
+ browsers.load_extensions,
)
@cached_property
@@ -727,8 +749,8 @@ def __init__(self, browsers: BrowsersResource) -> None:
self.delete_by_id = to_streamed_response_wrapper(
browsers.delete_by_id,
)
- self.upload_extensions = to_streamed_response_wrapper(
- browsers.upload_extensions,
+ self.load_extensions = to_streamed_response_wrapper(
+ browsers.load_extensions,
)
@cached_property
@@ -767,8 +789,8 @@ def __init__(self, browsers: AsyncBrowsersResource) -> None:
self.delete_by_id = async_to_streamed_response_wrapper(
browsers.delete_by_id,
)
- self.upload_extensions = async_to_streamed_response_wrapper(
- browsers.upload_extensions,
+ self.load_extensions = async_to_streamed_response_wrapper(
+ browsers.load_extensions,
)
@cached_property
diff --git a/src/kernel/types/__init__.py b/src/kernel/types/__init__.py
index bc28375f..6b49cf7f 100644
--- a/src/kernel/types/__init__.py
+++ b/src/kernel/types/__init__.py
@@ -47,7 +47,7 @@
from .invocation_update_response import InvocationUpdateResponse as InvocationUpdateResponse
from .deployment_retrieve_response import DeploymentRetrieveResponse as DeploymentRetrieveResponse
from .invocation_retrieve_response import InvocationRetrieveResponse as InvocationRetrieveResponse
-from .browser_upload_extensions_params import BrowserUploadExtensionsParams as BrowserUploadExtensionsParams
+from .browser_load_extensions_params import BrowserLoadExtensionsParams as BrowserLoadExtensionsParams
from .extension_download_from_chrome_store_params import (
ExtensionDownloadFromChromeStoreParams as ExtensionDownloadFromChromeStoreParams,
)
diff --git a/src/kernel/types/browser_create_params.py b/src/kernel/types/browser_create_params.py
index 4a1104c8..a0214a51 100644
--- a/src/kernel/types/browser_create_params.py
+++ b/src/kernel/types/browser_create_params.py
@@ -3,11 +3,11 @@
from __future__ import annotations
from typing import Iterable
-from typing_extensions import TypedDict
+from typing_extensions import Required, TypedDict
from .browser_persistence_param import BrowserPersistenceParam
-__all__ = ["BrowserCreateParams", "Extension", "Profile"]
+__all__ = ["BrowserCreateParams", "Extension", "Profile", "Viewport"]
class BrowserCreateParams(TypedDict, total=False):
@@ -58,6 +58,18 @@ class BrowserCreateParams(TypedDict, total=False):
specified value.
"""
+ viewport: Viewport
+ """Initial browser window size in pixels with optional refresh rate.
+
+ If omitted, image defaults apply (commonly 1024x768@60). Only specific viewport
+ configurations are supported. The server will reject unsupported combinations.
+ Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25,
+ 1440x900@25, 1024x768@60 If refresh_rate is not provided, it will be
+ automatically determined from the width and height if they match a supported
+ configuration exactly. Note: Higher resolutions may affect the responsiveness of
+ live view browser
+ """
+
class Extension(TypedDict, total=False):
id: str
@@ -85,3 +97,17 @@ class Profile(TypedDict, total=False):
If true, save changes made during the session back to the profile when the
session ends.
"""
+
+
+class Viewport(TypedDict, total=False):
+ height: Required[int]
+ """Browser window height in pixels."""
+
+ width: Required[int]
+ """Browser window width in pixels."""
+
+ refresh_rate: int
+ """Display refresh rate in Hz.
+
+ If omitted, automatically determined from width and height.
+ """
diff --git a/src/kernel/types/browser_create_response.py b/src/kernel/types/browser_create_response.py
index 9b14e426..d7ef603c 100644
--- a/src/kernel/types/browser_create_response.py
+++ b/src/kernel/types/browser_create_response.py
@@ -7,7 +7,21 @@
from .._models import BaseModel
from .browser_persistence import BrowserPersistence
-__all__ = ["BrowserCreateResponse"]
+__all__ = ["BrowserCreateResponse", "Viewport"]
+
+
+class Viewport(BaseModel):
+ height: int
+ """Browser window height in pixels."""
+
+ width: int
+ """Browser window width in pixels."""
+
+ refresh_rate: Optional[int] = None
+ """Display refresh rate in Hz.
+
+ If omitted, automatically determined from width and height.
+ """
class BrowserCreateResponse(BaseModel):
@@ -43,3 +57,15 @@ class BrowserCreateResponse(BaseModel):
proxy_id: Optional[str] = None
"""ID of the proxy associated with this browser session, if any."""
+
+ viewport: Optional[Viewport] = None
+ """Initial browser window size in pixels with optional refresh rate.
+
+ If omitted, image defaults apply (commonly 1024x768@60). Only specific viewport
+ configurations are supported. The server will reject unsupported combinations.
+ Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25,
+ 1440x900@25, 1024x768@60 If refresh_rate is not provided, it will be
+ automatically determined from the width and height if they match a supported
+ configuration exactly. Note: Higher resolutions may affect the responsiveness of
+ live view browser
+ """
diff --git a/src/kernel/types/browser_list_response.py b/src/kernel/types/browser_list_response.py
index 9c327201..22d72e18 100644
--- a/src/kernel/types/browser_list_response.py
+++ b/src/kernel/types/browser_list_response.py
@@ -8,7 +8,21 @@
from .._models import BaseModel
from .browser_persistence import BrowserPersistence
-__all__ = ["BrowserListResponse", "BrowserListResponseItem"]
+__all__ = ["BrowserListResponse", "BrowserListResponseItem", "BrowserListResponseItemViewport"]
+
+
+class BrowserListResponseItemViewport(BaseModel):
+ height: int
+ """Browser window height in pixels."""
+
+ width: int
+ """Browser window width in pixels."""
+
+ refresh_rate: Optional[int] = None
+ """Display refresh rate in Hz.
+
+ If omitted, automatically determined from width and height.
+ """
class BrowserListResponseItem(BaseModel):
@@ -45,5 +59,17 @@ class BrowserListResponseItem(BaseModel):
proxy_id: Optional[str] = None
"""ID of the proxy associated with this browser session, if any."""
+ viewport: Optional[BrowserListResponseItemViewport] = None
+ """Initial browser window size in pixels with optional refresh rate.
+
+ If omitted, image defaults apply (commonly 1024x768@60). Only specific viewport
+ configurations are supported. The server will reject unsupported combinations.
+ Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25,
+ 1440x900@25, 1024x768@60 If refresh_rate is not provided, it will be
+ automatically determined from the width and height if they match a supported
+ configuration exactly. Note: Higher resolutions may affect the responsiveness of
+ live view browser
+ """
+
BrowserListResponse: TypeAlias = List[BrowserListResponseItem]
diff --git a/src/kernel/types/browser_upload_extensions_params.py b/src/kernel/types/browser_load_extensions_params.py
similarity index 84%
rename from src/kernel/types/browser_upload_extensions_params.py
rename to src/kernel/types/browser_load_extensions_params.py
index ab0363cb..6212380c 100644
--- a/src/kernel/types/browser_upload_extensions_params.py
+++ b/src/kernel/types/browser_load_extensions_params.py
@@ -7,10 +7,10 @@
from .._types import FileTypes
-__all__ = ["BrowserUploadExtensionsParams", "Extension"]
+__all__ = ["BrowserLoadExtensionsParams", "Extension"]
-class BrowserUploadExtensionsParams(TypedDict, total=False):
+class BrowserLoadExtensionsParams(TypedDict, total=False):
extensions: Required[Iterable[Extension]]
"""List of extensions to upload and activate"""
diff --git a/src/kernel/types/browser_retrieve_response.py b/src/kernel/types/browser_retrieve_response.py
index 29ce4c17..2da39afa 100644
--- a/src/kernel/types/browser_retrieve_response.py
+++ b/src/kernel/types/browser_retrieve_response.py
@@ -7,7 +7,21 @@
from .._models import BaseModel
from .browser_persistence import BrowserPersistence
-__all__ = ["BrowserRetrieveResponse"]
+__all__ = ["BrowserRetrieveResponse", "Viewport"]
+
+
+class Viewport(BaseModel):
+ height: int
+ """Browser window height in pixels."""
+
+ width: int
+ """Browser window width in pixels."""
+
+ refresh_rate: Optional[int] = None
+ """Display refresh rate in Hz.
+
+ If omitted, automatically determined from width and height.
+ """
class BrowserRetrieveResponse(BaseModel):
@@ -43,3 +57,15 @@ class BrowserRetrieveResponse(BaseModel):
proxy_id: Optional[str] = None
"""ID of the proxy associated with this browser session, if any."""
+
+ viewport: Optional[Viewport] = None
+ """Initial browser window size in pixels with optional refresh rate.
+
+ If omitted, image defaults apply (commonly 1024x768@60). Only specific viewport
+ configurations are supported. The server will reject unsupported combinations.
+ Supported resolutions are: 2560x1440@10, 1920x1080@25, 1920x1200@25,
+ 1440x900@25, 1024x768@60 If refresh_rate is not provided, it will be
+ automatically determined from the width and height if they match a supported
+ configuration exactly. Note: Higher resolutions may affect the responsiveness of
+ live view browser
+ """
diff --git a/src/kernel/types/proxy_create_params.py b/src/kernel/types/proxy_create_params.py
index beb8a233..1f8d4b7d 100644
--- a/src/kernel/types/proxy_create_params.py
+++ b/src/kernel/types/proxy_create_params.py
@@ -36,12 +36,12 @@ class ProxyCreateParams(TypedDict, total=False):
class ConfigDatacenterProxyConfig(TypedDict, total=False):
country: Required[str]
- """ISO 3166 country code or EU for the proxy exit node."""
+ """ISO 3166 country code."""
class ConfigIspProxyConfig(TypedDict, total=False):
country: Required[str]
- """ISO 3166 country code or EU for the proxy exit node."""
+ """ISO 3166 country code."""
class ConfigResidentialProxyConfig(TypedDict, total=False):
@@ -55,10 +55,7 @@ class ConfigResidentialProxyConfig(TypedDict, total=False):
"""
country: str
- """ISO 3166 country code or EU for the proxy exit node.
-
- Required if `city` is provided.
- """
+ """ISO 3166 country code."""
os: Literal["windows", "macos", "android"]
"""Operating system of the residential device."""
@@ -143,10 +140,7 @@ class ConfigMobileProxyConfig(TypedDict, total=False):
"""
country: str
- """ISO 3166 country code or EU for the proxy exit node.
-
- Required if `city` is provided.
- """
+ """ISO 3166 country code"""
state: str
"""Two-letter state code."""
diff --git a/src/kernel/types/proxy_create_response.py b/src/kernel/types/proxy_create_response.py
index 84290af8..831c45f3 100644
--- a/src/kernel/types/proxy_create_response.py
+++ b/src/kernel/types/proxy_create_response.py
@@ -19,12 +19,12 @@
class ConfigDatacenterProxyConfig(BaseModel):
country: str
- """ISO 3166 country code or EU for the proxy exit node."""
+ """ISO 3166 country code."""
class ConfigIspProxyConfig(BaseModel):
country: str
- """ISO 3166 country code or EU for the proxy exit node."""
+ """ISO 3166 country code."""
class ConfigResidentialProxyConfig(BaseModel):
@@ -38,10 +38,7 @@ class ConfigResidentialProxyConfig(BaseModel):
"""
country: Optional[str] = None
- """ISO 3166 country code or EU for the proxy exit node.
-
- Required if `city` is provided.
- """
+ """ISO 3166 country code."""
os: Optional[Literal["windows", "macos", "android"]] = None
"""Operating system of the residential device."""
@@ -128,10 +125,7 @@ class ConfigMobileProxyConfig(BaseModel):
"""
country: Optional[str] = None
- """ISO 3166 country code or EU for the proxy exit node.
-
- Required if `city` is provided.
- """
+ """ISO 3166 country code"""
state: Optional[str] = None
"""Two-letter state code."""
diff --git a/src/kernel/types/proxy_list_response.py b/src/kernel/types/proxy_list_response.py
index cd804f32..96488816 100644
--- a/src/kernel/types/proxy_list_response.py
+++ b/src/kernel/types/proxy_list_response.py
@@ -20,12 +20,12 @@
class ProxyListResponseItemConfigDatacenterProxyConfig(BaseModel):
country: str
- """ISO 3166 country code or EU for the proxy exit node."""
+ """ISO 3166 country code."""
class ProxyListResponseItemConfigIspProxyConfig(BaseModel):
country: str
- """ISO 3166 country code or EU for the proxy exit node."""
+ """ISO 3166 country code."""
class ProxyListResponseItemConfigResidentialProxyConfig(BaseModel):
@@ -39,10 +39,7 @@ class ProxyListResponseItemConfigResidentialProxyConfig(BaseModel):
"""
country: Optional[str] = None
- """ISO 3166 country code or EU for the proxy exit node.
-
- Required if `city` is provided.
- """
+ """ISO 3166 country code."""
os: Optional[Literal["windows", "macos", "android"]] = None
"""Operating system of the residential device."""
@@ -129,10 +126,7 @@ class ProxyListResponseItemConfigMobileProxyConfig(BaseModel):
"""
country: Optional[str] = None
- """ISO 3166 country code or EU for the proxy exit node.
-
- Required if `city` is provided.
- """
+ """ISO 3166 country code"""
state: Optional[str] = None
"""Two-letter state code."""
diff --git a/src/kernel/types/proxy_retrieve_response.py b/src/kernel/types/proxy_retrieve_response.py
index f70ea705..4c2d63cc 100644
--- a/src/kernel/types/proxy_retrieve_response.py
+++ b/src/kernel/types/proxy_retrieve_response.py
@@ -19,12 +19,12 @@
class ConfigDatacenterProxyConfig(BaseModel):
country: str
- """ISO 3166 country code or EU for the proxy exit node."""
+ """ISO 3166 country code."""
class ConfigIspProxyConfig(BaseModel):
country: str
- """ISO 3166 country code or EU for the proxy exit node."""
+ """ISO 3166 country code."""
class ConfigResidentialProxyConfig(BaseModel):
@@ -38,10 +38,7 @@ class ConfigResidentialProxyConfig(BaseModel):
"""
country: Optional[str] = None
- """ISO 3166 country code or EU for the proxy exit node.
-
- Required if `city` is provided.
- """
+ """ISO 3166 country code."""
os: Optional[Literal["windows", "macos", "android"]] = None
"""Operating system of the residential device."""
@@ -128,10 +125,7 @@ class ConfigMobileProxyConfig(BaseModel):
"""
country: Optional[str] = None
- """ISO 3166 country code or EU for the proxy exit node.
-
- Required if `city` is provided.
- """
+ """ISO 3166 country code"""
state: Optional[str] = None
"""Two-letter state code."""
diff --git a/tests/api_resources/test_browsers.py b/tests/api_resources/test_browsers.py
index c3e7a7fe..e8ee60a4 100644
--- a/tests/api_resources/test_browsers.py
+++ b/tests/api_resources/test_browsers.py
@@ -48,6 +48,11 @@ def test_method_create_with_all_params(self, client: Kernel) -> None:
proxy_id="proxy_id",
stealth=True,
timeout_seconds=10,
+ viewport={
+ "height": 800,
+ "width": 1280,
+ "refresh_rate": 60,
+ },
)
assert_matches_type(BrowserCreateResponse, browser, path=["response"])
@@ -221,8 +226,8 @@ def test_path_params_delete_by_id(self, client: Kernel) -> None:
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
- def test_method_upload_extensions(self, client: Kernel) -> None:
- browser = client.browsers.upload_extensions(
+ def test_method_load_extensions(self, client: Kernel) -> None:
+ browser = client.browsers.load_extensions(
id="id",
extensions=[
{
@@ -235,8 +240,8 @@ def test_method_upload_extensions(self, client: Kernel) -> None:
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
- def test_raw_response_upload_extensions(self, client: Kernel) -> None:
- response = client.browsers.with_raw_response.upload_extensions(
+ def test_raw_response_load_extensions(self, client: Kernel) -> None:
+ response = client.browsers.with_raw_response.load_extensions(
id="id",
extensions=[
{
@@ -253,8 +258,8 @@ def test_raw_response_upload_extensions(self, client: Kernel) -> None:
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
- def test_streaming_response_upload_extensions(self, client: Kernel) -> None:
- with client.browsers.with_streaming_response.upload_extensions(
+ def test_streaming_response_load_extensions(self, client: Kernel) -> None:
+ with client.browsers.with_streaming_response.load_extensions(
id="id",
extensions=[
{
@@ -273,9 +278,9 @@ def test_streaming_response_upload_extensions(self, client: Kernel) -> None:
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
- def test_path_params_upload_extensions(self, client: Kernel) -> None:
+ def test_path_params_load_extensions(self, client: Kernel) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
- client.browsers.with_raw_response.upload_extensions(
+ client.browsers.with_raw_response.load_extensions(
id="",
extensions=[
{
@@ -318,6 +323,11 @@ async def test_method_create_with_all_params(self, async_client: AsyncKernel) ->
proxy_id="proxy_id",
stealth=True,
timeout_seconds=10,
+ viewport={
+ "height": 800,
+ "width": 1280,
+ "refresh_rate": 60,
+ },
)
assert_matches_type(BrowserCreateResponse, browser, path=["response"])
@@ -491,8 +501,8 @@ async def test_path_params_delete_by_id(self, async_client: AsyncKernel) -> None
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
- async def test_method_upload_extensions(self, async_client: AsyncKernel) -> None:
- browser = await async_client.browsers.upload_extensions(
+ async def test_method_load_extensions(self, async_client: AsyncKernel) -> None:
+ browser = await async_client.browsers.load_extensions(
id="id",
extensions=[
{
@@ -505,8 +515,8 @@ async def test_method_upload_extensions(self, async_client: AsyncKernel) -> None
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
- async def test_raw_response_upload_extensions(self, async_client: AsyncKernel) -> None:
- response = await async_client.browsers.with_raw_response.upload_extensions(
+ async def test_raw_response_load_extensions(self, async_client: AsyncKernel) -> None:
+ response = await async_client.browsers.with_raw_response.load_extensions(
id="id",
extensions=[
{
@@ -523,8 +533,8 @@ async def test_raw_response_upload_extensions(self, async_client: AsyncKernel) -
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
- async def test_streaming_response_upload_extensions(self, async_client: AsyncKernel) -> None:
- async with async_client.browsers.with_streaming_response.upload_extensions(
+ async def test_streaming_response_load_extensions(self, async_client: AsyncKernel) -> None:
+ async with async_client.browsers.with_streaming_response.load_extensions(
id="id",
extensions=[
{
@@ -543,9 +553,9 @@ async def test_streaming_response_upload_extensions(self, async_client: AsyncKer
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
- async def test_path_params_upload_extensions(self, async_client: AsyncKernel) -> None:
+ async def test_path_params_load_extensions(self, async_client: AsyncKernel) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
- await async_client.browsers.with_raw_response.upload_extensions(
+ await async_client.browsers.with_raw_response.load_extensions(
id="",
extensions=[
{