Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions hyperbrowser/models/__init__.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -134,6 +134,7 @@
StartCuaTaskParams,
StartCuaTaskResponse,
CuaApiKeys,
CuaBaseUrls,
CuaTaskStatus,
)
from .agents.hyper_agent import (
Expand DownExpand Up@@ -493,6 +494,7 @@
"GeminiComputerUseApiKeys",
"GrokComputerUseApiKeys",
"CuaApiKeys",
"CuaBaseUrls",
"HyperAgentApiKeys",
"GrokComputerUseLlm",
"GrokReasoningEffort",
Expand Down
15 changes: 15 additions & 0 deletions hyperbrowser/models/agents/cua.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -22,6 +22,18 @@ class CuaApiKeys(BaseModel):
openai: Optional[str] = Field(default=None, serialization_alias="openai")


class CuaBaseUrls(BaseModel):
"""
Provider base URLs for the CUA task.
"""

model_config = ConfigDict(
populate_by_alias=True,
)

openai: Optional[str] = Field(default=None, serialization_alias="openai")


class StartCuaTaskParams(BaseModel):
"""
Parameters for creating a new CUA task.
Expand All@@ -46,6 +58,9 @@ class StartCuaTaskParams(BaseModel):
default=None, serialization_alias="useCustomApiKeys"
)
api_keys: Optional[CuaApiKeys] = Field(default=None, serialization_alias="apiKeys")
base_urls: Optional[CuaBaseUrls] = Field(
default=None, serialization_alias="baseUrls"
)
use_computer_action: Optional[bool] = Field(
default=None, serialization_alias="useComputerAction"
)
Expand Down
2 changes: 2 additions & 0 deletions hyperbrowser/types/__init__.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,6 +16,7 @@
BrowserUseApiKeys,
ClaudeComputerUseApiKeys,
CuaApiKeys,
CuaBaseUrls,
GeminiComputerUseApiKeys,
GrokComputerUseApiKeys,
HyperAgentApiKeys,
Expand DownExpand Up@@ -173,6 +174,7 @@
"BrowserUseApiKeys",
"ClaudeComputerUseApiKeys",
"CuaApiKeys",
"CuaBaseUrls",
"GeminiComputerUseApiKeys",
"GrokComputerUseApiKeys",
"HyperAgentApiKeys",
Expand Down
8 changes: 8 additions & 0 deletions hyperbrowser/types/agents.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -123,6 +123,12 @@ class CuaApiKeys(TypedDict, total=False):
openai: Optional[str]


class CuaBaseUrls(TypedDict, total=False):
"""Provider base URLs for an OpenAI CUA task."""

openai: Optional[str]


class StartCuaTaskParams(TypedDict, total=False):
"""Parameters for starting an OpenAI CUA task."""

Expand All@@ -135,6 +141,7 @@ class StartCuaTaskParams(TypedDict, total=False):
session_options: Optional[CreateSessionParams]
use_custom_api_keys: Optional[bool]
api_keys: Optional[CuaApiKeys]
base_urls: Optional[CuaBaseUrls]
use_computer_action: Optional[bool]


Expand DownExpand Up@@ -165,6 +172,7 @@ class StartHyperAgentTaskParams(TypedDict, total=False):
"BrowserUseApiKeys",
"ClaudeComputerUseApiKeys",
"CuaApiKeys",
"CuaBaseUrls",
"GeminiComputerUseApiKeys",
"GrokComputerUseApiKeys",
"HyperAgentApiKeys",
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "hyperbrowser"
version = "1.2.2"
version = "1.2.3"
description = "Python SDK for hyperbrowser"
authors = ["Nikhil Shahi <nshahi1998@gmail.com>"]
license = "MIT"
Expand Down
32 changes: 32 additions & 0 deletions tests/test_request_compat.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,9 +8,11 @@
normalize_pydantic_schema,
)
from hyperbrowser.models import (
CuaBaseUrls,
CreateSandboxParams,
CreateSessionParams,
StartBrowserUseTaskParams,
StartCuaTaskParams,
)
from hyperbrowser.tools import _normalize_extract_tool_params

Expand DownExpand Up@@ -76,6 +78,36 @@ def test_mapping_uses_existing_cross_field_validation():
)


def test_cua_custom_base_url_serializes_for_mapping_and_legacy_model():
mapping = {
"task": "Complete the task",
"use_custom_api_keys": True,
"api_keys": {"openai": "openai-key"},
"base_urls": {
"openai": "https://example.openai.azure.com/openai/v1/",
},
}
legacy = StartCuaTaskParams(
task="Complete the task",
use_custom_api_keys=True,
api_keys={"openai": "openai-key"},
base_urls=CuaBaseUrls(openai="https://example.openai.azure.com/openai/v1/"),
)

assert dump_request(mapping, StartCuaTaskParams) == dump_request(
legacy,
StartCuaTaskParams,
)
assert dump_request(mapping, StartCuaTaskParams) == {
"task": "Complete the task",
"useCustomApiKeys": True,
"apiKeys": {"openai": "openai-key"},
"baseUrls": {
"openai": "https://example.openai.azure.com/openai/v1/",
},
}


def test_raw_json_schema_is_copied_without_rewriting_or_dereferencing():
schema = {
"$defs": {
Expand Down
20 changes: 20 additions & 0 deletions tests/typecheck/valid_requests.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -96,6 +96,16 @@ def valid_sync_requests(client: Hyperbrowser) -> None:
"session_options": {"use_stealth": True},
}
)
client.agents.cua.start(
{
"task": "Complete the task",
"use_custom_api_keys": True,
"api_keys": {"openai": "openai-key"},
"base_urls": {
"openai": "https://example.openai.azure.com/openai/v1/",
},
}
)
client.sandboxes.create(
{
"image_name": "node",
Expand DownExpand Up@@ -182,6 +192,16 @@ async def valid_async_requests(client: AsyncHyperbrowser) -> None:
},
}
)
await client.agents.cua.start(
{
"task": "Complete the task",
"use_custom_api_keys": True,
"api_keys": {"openai": "openai-key"},
"base_urls": {
"openai": "https://example.openai.azure.com/openai/v1/",
},
}
)
await client.sandboxes.create(
{
"snapshot_name": "ready-to-run",
Expand Down