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: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ client.crawl # Website crawling jobs
client.extract # Data extraction jobs
client.web # Web fetch/search operations
client.web.batch_fetch # Batch web fetch operations
client.agents # AI agent integrations (browser_use, cua, claude_computer_use, hyper_agent, gemini_computer_use, grok_computer_use, meta_computer_use)
client.agents # AI agent integrations (browser_use, cua, claude_computer_use, hyper_agent, gemini_computer_use, grok_computer_use, jev_computer_use, meta_computer_use)
client.profiles # Browser profile management
client.extensions # Browser extension management
client.team # Team/credit info
Expand Down
2 changes: 2 additions & 0 deletions hyperbrowser/client/managers/async_manager/agents/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from .hyper_agent import HyperAgentManager
from .gemini_computer_use import GeminiComputerUseManager
from .grok_computer_use import GrokComputerUseManager
from .jev_computer_use import JevComputerUseManager
from .meta_computer_use import MetaComputerUseManager


Expand All @@ -15,4 +16,5 @@ def __init__(self, client):
self.hyper_agent = HyperAgentManager(client)
self.gemini_computer_use = GeminiComputerUseManager(client)
self.grok_computer_use = GrokComputerUseManager(client)
self.jev_computer_use = JevComputerUseManager(client)
self.meta_computer_use = MetaComputerUseManager(client)
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import asyncio
from typing import Union

from hyperbrowser.client._request import dump_request
from hyperbrowser.exceptions import HyperbrowserError
from hyperbrowser.types import (
StartJevComputerUseTaskParams as StartJevComputerUseTaskParamsDict,
)

from .....models import (
POLLING_ATTEMPTS,
BasicResponse,
JevComputerUseTaskResponse,
JevComputerUseTaskStatusResponse,
StartJevComputerUseTaskParams,
StartJevComputerUseTaskResponse,
)


class JevComputerUseManager:
def __init__(self, client):
self._client = client

async def start(
self,
params: Union[
StartJevComputerUseTaskParamsDict,
StartJevComputerUseTaskParams,
],
) -> StartJevComputerUseTaskResponse:
response = await self._client.transport.post(
self._client._build_url("/task/jev"),
data=dump_request(params, StartJevComputerUseTaskParams),
)
return StartJevComputerUseTaskResponse(**response.data)

async def get(self, job_id: str) -> JevComputerUseTaskResponse:
response = await self._client.transport.get(
self._client._build_url(f"/task/jev/{job_id}")
)
return JevComputerUseTaskResponse(**response.data)

async def get_status(self, job_id: str) -> JevComputerUseTaskStatusResponse:
response = await self._client.transport.get(
self._client._build_url(f"/task/jev/{job_id}/status")
)
return JevComputerUseTaskStatusResponse(**response.data)

async def stop(self, job_id: str) -> BasicResponse:
response = await self._client.transport.put(
self._client._build_url(f"/task/jev/{job_id}/stop")
)
return BasicResponse(**response.data)

async def start_and_wait(
self,
params: Union[
StartJevComputerUseTaskParamsDict,
StartJevComputerUseTaskParams,
],
) -> JevComputerUseTaskResponse:
job_start_resp = await self.start(params)
job_id = job_start_resp.job_id
if not job_id:
raise HyperbrowserError("Failed to start Jev Computer Use task job")

failures = 0
while True:
try:
job_response = await self.get_status(job_id)
if (
job_response.status == "completed"
or job_response.status == "failed"
or job_response.status == "stopped"
):
return await self.get(job_id)
failures = 0
except Exception as e:
failures += 1
if failures >= POLLING_ATTEMPTS:
raise HyperbrowserError(
f"Failed to poll Jev Computer Use task job {job_id} after {POLLING_ATTEMPTS} attempts: {e}"
)
await asyncio.sleep(2)
2 changes: 2 additions & 0 deletions hyperbrowser/client/managers/sync_manager/agents/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from .hyper_agent import HyperAgentManager
from .gemini_computer_use import GeminiComputerUseManager
from .grok_computer_use import GrokComputerUseManager
from .jev_computer_use import JevComputerUseManager
from .meta_computer_use import MetaComputerUseManager


Expand All @@ -15,4 +16,5 @@ def __init__(self, client):
self.hyper_agent = HyperAgentManager(client)
self.gemini_computer_use = GeminiComputerUseManager(client)
self.grok_computer_use = GrokComputerUseManager(client)
self.jev_computer_use = JevComputerUseManager(client)
self.meta_computer_use = MetaComputerUseManager(client)
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import time
from typing import Union

from hyperbrowser.client._request import dump_request
from hyperbrowser.exceptions import HyperbrowserError
from hyperbrowser.types import (
StartJevComputerUseTaskParams as StartJevComputerUseTaskParamsDict,
)

from .....models import (
POLLING_ATTEMPTS,
BasicResponse,
JevComputerUseTaskResponse,
JevComputerUseTaskStatusResponse,
StartJevComputerUseTaskParams,
StartJevComputerUseTaskResponse,
)


class JevComputerUseManager:
def __init__(self, client):
self._client = client

def start(
self,
params: Union[
StartJevComputerUseTaskParamsDict,
StartJevComputerUseTaskParams,
],
) -> StartJevComputerUseTaskResponse:
response = self._client.transport.post(
self._client._build_url("/task/jev"),
data=dump_request(params, StartJevComputerUseTaskParams),
)
return StartJevComputerUseTaskResponse(**response.data)

def get(self, job_id: str) -> JevComputerUseTaskResponse:
response = self._client.transport.get(
self._client._build_url(f"/task/jev/{job_id}")
)
return JevComputerUseTaskResponse(**response.data)

def get_status(self, job_id: str) -> JevComputerUseTaskStatusResponse:
response = self._client.transport.get(
self._client._build_url(f"/task/jev/{job_id}/status")
)
return JevComputerUseTaskStatusResponse(**response.data)

def stop(self, job_id: str) -> BasicResponse:
response = self._client.transport.put(
self._client._build_url(f"/task/jev/{job_id}/stop")
)
return BasicResponse(**response.data)

def start_and_wait(
self,
params: Union[
StartJevComputerUseTaskParamsDict,
StartJevComputerUseTaskParams,
],
) -> JevComputerUseTaskResponse:
job_start_resp = self.start(params)
job_id = job_start_resp.job_id
if not job_id:
raise HyperbrowserError("Failed to start Jev Computer Use task job")

failures = 0
while True:
try:
job_response = self.get_status(job_id)
if (
job_response.status == "completed"
or job_response.status == "failed"
or job_response.status == "stopped"
):
return self.get(job_id)
failures = 0
except Exception as e:
failures += 1
if failures >= POLLING_ATTEMPTS:
raise HyperbrowserError(
f"Failed to poll Jev Computer Use task job {job_id} after {POLLING_ATTEMPTS} attempts: {e}"
)
time.sleep(2)
20 changes: 20 additions & 0 deletions hyperbrowser/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,15 @@
StartMetaComputerUseTaskResponse,
MetaComputerUseApiKeys,
)
from .agents.jev_computer_use import (
JevComputerUseTaskStatus,
JevComputerUseTaskData,
JevComputerUseTaskResponse,
JevComputerUseTaskStatusResponse,
StartJevComputerUseTaskParams,
StartJevComputerUseTaskResponse,
JevComputerUseApiKeys,
)
from .agents.cua import (
CuaTaskData,
CuaTaskResponse,
Expand Down Expand Up @@ -175,6 +184,8 @@
GrokReasoningEffort,
MetaComputerUseLlm,
MetaReasoningEffort,
JevComputerUseLlm,
JevTextLlm,
Country,
DownloadsStatus,
FetchScreenshotFormat,
Expand Down Expand Up @@ -521,6 +532,12 @@
"MetaComputerUseTaskStatusResponse",
"StartMetaComputerUseTaskParams",
"StartMetaComputerUseTaskResponse",
"JevComputerUseTaskStatus",
"JevComputerUseTaskData",
"JevComputerUseTaskResponse",
"JevComputerUseTaskStatusResponse",
"StartJevComputerUseTaskParams",
"StartJevComputerUseTaskResponse",
"CuaTaskStatus",
"CuaTaskData",
"CuaTaskResponse",
Expand All @@ -531,6 +548,7 @@
"ClaudeComputerUseApiKeys",
"GeminiComputerUseApiKeys",
"GrokComputerUseApiKeys",
"JevComputerUseApiKeys",
"MetaComputerUseApiKeys",
"CuaApiKeys",
"CuaBaseUrls",
Expand All @@ -539,6 +557,8 @@
"GrokReasoningEffort",
"MetaComputerUseLlm",
"MetaReasoningEffort",
"JevComputerUseLlm",
"JevTextLlm",
"HyperAgentOutputV110",
"HyperAgentStepV110",
# crawl
Expand Down
119 changes: 119 additions & 0 deletions hyperbrowser/models/agents/jev_computer_use.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
from __future__ import annotations

from typing import Any, Dict, List, Literal, Optional

from pydantic import BaseModel, ConfigDict, Field

from ..session import CreateSessionParams
from ..consts import JevComputerUseLlm, JevTextLlm

JevComputerUseTaskStatus = Literal[
"pending", "running", "completed", "failed", "stopped"
]


class JevComputerUseApiKeys(BaseModel):
"""
API keys for the Jev Computer Use task.
"""

model_config = ConfigDict(
populate_by_alias=True,
)

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


class StartJevComputerUseTaskParams(BaseModel):
"""
Parameters for creating a new Jev Computer Use task.
"""

model_config = ConfigDict(
populate_by_alias=True,
)

task: str
llm: Optional[JevComputerUseLlm] = Field(default=None, serialization_alias="llm")
text_llm: Optional[JevTextLlm] = Field(default=None, serialization_alias="textLlm")
session_id: Optional[str] = Field(default=None, serialization_alias="sessionId")
max_failures: Optional[int] = Field(default=None, serialization_alias="maxFailures")
max_steps: Optional[int] = Field(default=None, serialization_alias="maxSteps")
keep_browser_open: Optional[bool] = Field(
default=None, serialization_alias="keepBrowserOpen"
)
session_options: Optional[CreateSessionParams] = Field(
default=None, serialization_alias="sessionOptions"
)
use_custom_api_keys: Optional[bool] = Field(
default=None, serialization_alias="useCustomApiKeys"
)
api_keys: Optional[JevComputerUseApiKeys] = Field(
default=None, serialization_alias="apiKeys"
)


class StartJevComputerUseTaskResponse(BaseModel):
"""
Response from starting a Jev Computer Use task.
"""

model_config = ConfigDict(
populate_by_alias=True,
)

job_id: str = Field(alias="jobId")
live_url: Optional[str] = Field(default=None, alias="liveUrl")


class JevComputerUseTaskStatusResponse(BaseModel):
"""
Response from getting a Jev Computer Use task status.
"""

model_config = ConfigDict(
populate_by_alias=True,
)

status: JevComputerUseTaskStatus


class JevComputerUseTaskData(BaseModel):
model_config = ConfigDict(
populate_by_alias=True,
)

steps: List[Dict[str, Any]]
final_result: Optional[str] = Field(default=None, alias="finalResult")


class JevComputerUseTaskMetadata(BaseModel):
model_config = ConfigDict(
populate_by_alias=True,
)

input_tokens: Optional[int] = Field(default=None, alias="inputTokens")
output_tokens: Optional[int] = Field(default=None, alias="outputTokens")
num_task_steps_completed: Optional[int] = Field(
default=None, alias="numTaskStepsCompleted"
)


class JevComputerUseTaskResponse(BaseModel):
"""
Response from a Jev Computer Use task.
"""

model_config = ConfigDict(
populate_by_alias=True,
)

job_id: str = Field(alias="jobId")
status: JevComputerUseTaskStatus
metadata: Optional[JevComputerUseTaskMetadata] = Field(
default=None, alias="metadata"
)
data: Optional[JevComputerUseTaskData] = Field(default=None, alias="data")
error: Optional[str] = Field(default=None, alias="error")
live_url: Optional[str] = Field(default=None, alias="liveUrl")
Loading