hyperbrowser 1.10.0__tar.gz → 1.11.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/PKG-INFO +35 -1
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/README.md +34 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/async_manager/session.py +3 -0
- hyperbrowser-1.11.0/hyperbrowser/client/managers/async_manager/webmcp.py +98 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sync_manager/session.py +3 -0
- hyperbrowser-1.11.0/hyperbrowser/client/managers/sync_manager/webmcp.py +98 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/models/__init__.py +29 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/models/session.py +6 -0
- hyperbrowser-1.11.0/hyperbrowser/models/webmcp.py +126 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/transport/async_transport.py +18 -2
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/transport/base.py +8 -1
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/transport/sync.py +18 -2
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/types/__init__.py +9 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/types/session.py +1 -0
- hyperbrowser-1.11.0/hyperbrowser/types/webmcp.py +22 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/pyproject.toml +1 -1
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/LICENSE +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/__init__.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/build_context.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/_request.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/async_client.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/base.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/async_manager/agents/__init__.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/async_manager/agents/browser_use.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/async_manager/agents/claude_computer_use.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/async_manager/agents/cua.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/async_manager/agents/gemini_computer_use.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/async_manager/agents/grok_computer_use.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/async_manager/agents/hyper_agent.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/async_manager/agents/jev_computer_use.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/async_manager/agents/meta_computer_use.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/async_manager/computer_action.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/async_manager/crawl.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/async_manager/extension.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/async_manager/extract.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/async_manager/profile.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/async_manager/sandbox.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/async_manager/sandboxes/__init__.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/async_manager/sandboxes/sandbox_files.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/async_manager/sandboxes/sandbox_processes.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/async_manager/sandboxes/sandbox_terminal.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/async_manager/sandboxes/sandbox_transport.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/async_manager/scrape.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/async_manager/team.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/async_manager/volume.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/async_manager/web/__init__.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/async_manager/web/batch_fetch.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/async_manager/web/crawl.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sandboxes/__init__.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sandboxes/dockerfile_analysis.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sandboxes/dockerignore.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sandboxes/image_build.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sandboxes/image_resolution.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sandboxes/process_output.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sandboxes/shared.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sync_manager/agents/__init__.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sync_manager/agents/browser_use.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sync_manager/agents/claude_computer_use.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sync_manager/agents/cua.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sync_manager/agents/gemini_computer_use.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sync_manager/agents/grok_computer_use.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sync_manager/agents/hyper_agent.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sync_manager/agents/jev_computer_use.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sync_manager/agents/meta_computer_use.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sync_manager/computer_action.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sync_manager/crawl.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sync_manager/extension.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sync_manager/extract.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sync_manager/profile.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sync_manager/sandbox.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sync_manager/sandboxes/__init__.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sync_manager/sandboxes/sandbox_files.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sync_manager/sandboxes/sandbox_processes.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sync_manager/sandboxes/sandbox_terminal.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sync_manager/sandboxes/sandbox_transport.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sync_manager/scrape.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sync_manager/team.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sync_manager/volume.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sync_manager/web/__init__.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sync_manager/web/batch_fetch.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sync_manager/web/crawl.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/sync.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/config.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/exceptions.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/image_builds.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/models/_parsers.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/models/agents/browser_use.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/models/agents/claude_computer_use.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/models/agents/cua.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/models/agents/gemini_computer_use.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/models/agents/grok_computer_use.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/models/agents/hyper_agent.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/models/agents/jev_computer_use.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/models/agents/meta_computer_use.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/models/computer_action.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/models/consts.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/models/crawl.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/models/extension.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/models/extract.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/models/profile.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/models/sandbox.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/models/scrape.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/models/team.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/models/volume.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/models/web/batch_fetch.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/models/web/branding.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/models/web/common.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/models/web/crawl.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/models/web/fetch.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/models/web/search.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/py.typed +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/sandbox_common.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/tools/__init__.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/tools/anthropic.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/tools/openai.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/tools/schema.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/types/_json.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/types/agents.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/types/computer_action.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/types/crawl.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/types/extension.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/types/extract.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/types/profile.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/types/sandbox.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/types/scrape.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/types/volume.py +0 -0
- {hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/types/web.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hyperbrowser
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.11.0
|
|
4
4
|
Summary: Python SDK for hyperbrowser
|
|
5
5
|
License: MIT
|
|
6
6
|
License-File: LICENSE
|
|
@@ -62,6 +62,40 @@ Profile names must match `^[A-Za-z0-9._-]+$`.
|
|
|
62
62
|
|
|
63
63
|
`base_url` and `HYPERBROWSER_BASE_URL` accept either `https://host` or `https://host/api`. The client normalizes both to the same control-plane base URL.
|
|
64
64
|
|
|
65
|
+
## WebMCP page tools
|
|
66
|
+
|
|
67
|
+
Create a session with `{"enable_web_mcp": True}` (default: false), then navigate
|
|
68
|
+
to a page that exposes WebMCP tools using Playwright. With that session open:
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
discovery = client.sessions.webmcp.list_tools(session.id)
|
|
72
|
+
# Select a tool using its name, source page/frame, and input schema.
|
|
73
|
+
tool = next(tool for tool in discovery.tools if tool.name == "search")
|
|
74
|
+
result = client.sessions.webmcp.invoke(session.id, {
|
|
75
|
+
"tool_ref": tool.tool_ref,
|
|
76
|
+
"input": {"query": "flights to Tokyo"}, # Match the selected tool's schema.
|
|
77
|
+
})
|
|
78
|
+
print(result.status, result.output)
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
For long-running tools or forms awaiting human submission, use
|
|
82
|
+
`client.sessions.webmcp.start(session_id, params)`, then
|
|
83
|
+
`client.sessions.webmcp.get_result(session_id, invocation_id, {"wait_seconds": 30})`
|
|
84
|
+
until the status is terminal. `client.sessions.webmcp.cancel(session_id, invocation_id)`
|
|
85
|
+
requests best-effort cancellation. Blocking invocation defaults to 60 seconds
|
|
86
|
+
(maximum 120); `start` defaults to 300 seconds (maximum 3,600) via `timeout_seconds`.
|
|
87
|
+
All five methods also work with `AsyncHyperbrowser` by adding `await`.
|
|
88
|
+
|
|
89
|
+
Discover tools again after navigation. Invocations never automatically retry;
|
|
90
|
+
losing a response can leave an unknown outcome. Handles are ephemeral and
|
|
91
|
+
terminal results expire after 10 minutes or earlier eviction. Check result
|
|
92
|
+
status and truncation metadata before using output. Tool input and output keys
|
|
93
|
+
are not renamed. Request TypedDicts are available in `hyperbrowser.types`, and
|
|
94
|
+
Pydantic request/response models in `hyperbrowser.models`.
|
|
95
|
+
|
|
96
|
+
See the [WebMCP guide](https://hyperbrowser.ai/docs/sessions/webmcp) for complete
|
|
97
|
+
examples, cancellation behavior, human submission, and limits.
|
|
98
|
+
|
|
65
99
|
## Usage
|
|
66
100
|
|
|
67
101
|
Hyperbrowser 1.0 accepts plain dictionaries for request parameters. Method
|
|
@@ -34,6 +34,40 @@ Profile names must match `^[A-Za-z0-9._-]+$`.
|
|
|
34
34
|
|
|
35
35
|
`base_url` and `HYPERBROWSER_BASE_URL` accept either `https://host` or `https://host/api`. The client normalizes both to the same control-plane base URL.
|
|
36
36
|
|
|
37
|
+
## WebMCP page tools
|
|
38
|
+
|
|
39
|
+
Create a session with `{"enable_web_mcp": True}` (default: false), then navigate
|
|
40
|
+
to a page that exposes WebMCP tools using Playwright. With that session open:
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
discovery = client.sessions.webmcp.list_tools(session.id)
|
|
44
|
+
# Select a tool using its name, source page/frame, and input schema.
|
|
45
|
+
tool = next(tool for tool in discovery.tools if tool.name == "search")
|
|
46
|
+
result = client.sessions.webmcp.invoke(session.id, {
|
|
47
|
+
"tool_ref": tool.tool_ref,
|
|
48
|
+
"input": {"query": "flights to Tokyo"}, # Match the selected tool's schema.
|
|
49
|
+
})
|
|
50
|
+
print(result.status, result.output)
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
For long-running tools or forms awaiting human submission, use
|
|
54
|
+
`client.sessions.webmcp.start(session_id, params)`, then
|
|
55
|
+
`client.sessions.webmcp.get_result(session_id, invocation_id, {"wait_seconds": 30})`
|
|
56
|
+
until the status is terminal. `client.sessions.webmcp.cancel(session_id, invocation_id)`
|
|
57
|
+
requests best-effort cancellation. Blocking invocation defaults to 60 seconds
|
|
58
|
+
(maximum 120); `start` defaults to 300 seconds (maximum 3,600) via `timeout_seconds`.
|
|
59
|
+
All five methods also work with `AsyncHyperbrowser` by adding `await`.
|
|
60
|
+
|
|
61
|
+
Discover tools again after navigation. Invocations never automatically retry;
|
|
62
|
+
losing a response can leave an unknown outcome. Handles are ephemeral and
|
|
63
|
+
terminal results expire after 10 minutes or earlier eviction. Check result
|
|
64
|
+
status and truncation metadata before using output. Tool input and output keys
|
|
65
|
+
are not renamed. Request TypedDicts are available in `hyperbrowser.types`, and
|
|
66
|
+
Pydantic request/response models in `hyperbrowser.models`.
|
|
67
|
+
|
|
68
|
+
See the [WebMCP guide](https://hyperbrowser.ai/docs/sessions/webmcp) for complete
|
|
69
|
+
examples, cancellation behavior, human submission, and limits.
|
|
70
|
+
|
|
37
71
|
## Usage
|
|
38
72
|
|
|
39
73
|
Hyperbrowser 1.0 accepts plain dictionaries for request parameters. Method
|
{hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/async_manager/session.py
RENAMED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import warnings
|
|
2
|
+
|
|
3
|
+
from .webmcp import WebMCPManager
|
|
2
4
|
from collections.abc import Mapping
|
|
3
5
|
from typing import IO, List, Optional, Union, overload
|
|
4
6
|
|
|
@@ -68,6 +70,7 @@ class SessionManager:
|
|
|
68
70
|
def __init__(self, client):
|
|
69
71
|
self._client = client
|
|
70
72
|
self.event_logs = SessionEventLogsManager(client)
|
|
73
|
+
self.webmcp = WebMCPManager(client)
|
|
71
74
|
|
|
72
75
|
async def create(
|
|
73
76
|
self,
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
from typing import Optional, Union
|
|
2
|
+
from urllib.parse import quote
|
|
3
|
+
|
|
4
|
+
from hyperbrowser.client._request import coerce_request, dump_request
|
|
5
|
+
from hyperbrowser.models.webmcp import (
|
|
6
|
+
WebMCPInvocation,
|
|
7
|
+
WebMCPInvokeParams,
|
|
8
|
+
WebMCPInvokeResult,
|
|
9
|
+
WebMCPResultParams,
|
|
10
|
+
WebMCPStartParams,
|
|
11
|
+
WebMCPToolsResponse,
|
|
12
|
+
)
|
|
13
|
+
from hyperbrowser.types.webmcp import (
|
|
14
|
+
WebMCPInvokeParams as WebMCPInvokeParamsDict,
|
|
15
|
+
WebMCPResultParams as WebMCPResultParamsDict,
|
|
16
|
+
WebMCPStartParams as WebMCPStartParamsDict,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class WebMCPManager:
|
|
21
|
+
"""Discover and invoke page tools in sessions created with enable_web_mcp=True."""
|
|
22
|
+
|
|
23
|
+
def __init__(self, client):
|
|
24
|
+
self._client = client
|
|
25
|
+
|
|
26
|
+
def _url(self, session_id: str, suffix: str) -> str:
|
|
27
|
+
return self._client._build_url(
|
|
28
|
+
f"/session/{quote(session_id, safe='')}/webmcp{suffix}"
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
async def list_tools(self, session_id: str) -> WebMCPToolsResponse:
|
|
32
|
+
"""Discover document-bound tools across the session's tabs and frames."""
|
|
33
|
+
response = await self._client.transport.get(
|
|
34
|
+
self._url(session_id, "/tools"), timeout=max(self._client.timeout, 40)
|
|
35
|
+
)
|
|
36
|
+
return WebMCPToolsResponse(**response.data)
|
|
37
|
+
|
|
38
|
+
async def invoke(
|
|
39
|
+
self,
|
|
40
|
+
session_id: str,
|
|
41
|
+
params: Union[WebMCPInvokeParamsDict, WebMCPInvokeParams],
|
|
42
|
+
) -> WebMCPInvokeResult:
|
|
43
|
+
"""Invoke once and wait. A form can return awaiting_submission with a handle.
|
|
44
|
+
|
|
45
|
+
This POST is never automatically retried: losing its response can leave the
|
|
46
|
+
outcome unknown, and repeating it could duplicate a side effect.
|
|
47
|
+
"""
|
|
48
|
+
request = coerce_request(params, WebMCPInvokeParams)
|
|
49
|
+
response = await self._client.transport.post(
|
|
50
|
+
self._url(session_id, "/invoke"),
|
|
51
|
+
data=dump_request(request, WebMCPInvokeParams),
|
|
52
|
+
timeout=max(self._client.timeout, request.timeout_seconds + 35),
|
|
53
|
+
)
|
|
54
|
+
return WebMCPInvokeResult(**response.data)
|
|
55
|
+
|
|
56
|
+
async def start(
|
|
57
|
+
self,
|
|
58
|
+
session_id: str,
|
|
59
|
+
params: Union[WebMCPStartParamsDict, WebMCPStartParams],
|
|
60
|
+
) -> WebMCPInvocation:
|
|
61
|
+
"""Start once and return a handle; use get_result to observe its outcome."""
|
|
62
|
+
response = await self._client.transport.post(
|
|
63
|
+
self._url(session_id, "/invocations"),
|
|
64
|
+
data=dump_request(params, WebMCPStartParams),
|
|
65
|
+
timeout=max(self._client.timeout, 40),
|
|
66
|
+
)
|
|
67
|
+
return WebMCPInvocation(**response.data)
|
|
68
|
+
|
|
69
|
+
async def get_result(
|
|
70
|
+
self,
|
|
71
|
+
session_id: str,
|
|
72
|
+
invocation_id: str,
|
|
73
|
+
params: Optional[Union[WebMCPResultParamsDict, WebMCPResultParams]] = None,
|
|
74
|
+
) -> WebMCPInvocation:
|
|
75
|
+
"""Read or long-poll once. Running/awaiting_submission can remain pending.
|
|
76
|
+
|
|
77
|
+
Handles are in memory. Terminal results expire after 10 minutes and may
|
|
78
|
+
be evicted sooner; browser shutdown or receiver restart also loses them.
|
|
79
|
+
"""
|
|
80
|
+
request = coerce_request(
|
|
81
|
+
params if params is not None else {}, WebMCPResultParams
|
|
82
|
+
)
|
|
83
|
+
response = await self._client.transport.get(
|
|
84
|
+
self._url(session_id, f"/invocations/{quote(invocation_id, safe='')}"),
|
|
85
|
+
params=dump_request(request, WebMCPResultParams),
|
|
86
|
+
timeout=max(self._client.timeout, request.wait_seconds + 20),
|
|
87
|
+
)
|
|
88
|
+
return WebMCPInvocation(**response.data)
|
|
89
|
+
|
|
90
|
+
async def cancel(self, session_id: str, invocation_id: str) -> WebMCPInvocation:
|
|
91
|
+
"""Request best-effort cancellation. Completion can win; side effects persist."""
|
|
92
|
+
response = await self._client.transport.post(
|
|
93
|
+
self._url(
|
|
94
|
+
session_id, f"/invocations/{quote(invocation_id, safe='')}/cancel"
|
|
95
|
+
),
|
|
96
|
+
timeout=max(self._client.timeout, 20),
|
|
97
|
+
)
|
|
98
|
+
return WebMCPInvocation(**response.data)
|
{hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sync_manager/session.py
RENAMED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import warnings
|
|
2
|
+
|
|
3
|
+
from .webmcp import WebMCPManager
|
|
2
4
|
from collections.abc import Mapping
|
|
3
5
|
from typing import IO, List, Optional, Union, overload
|
|
4
6
|
|
|
@@ -68,6 +70,7 @@ class SessionManager:
|
|
|
68
70
|
def __init__(self, client):
|
|
69
71
|
self._client = client
|
|
70
72
|
self.event_logs = SessionEventLogsManager(client)
|
|
73
|
+
self.webmcp = WebMCPManager(client)
|
|
71
74
|
|
|
72
75
|
def create(
|
|
73
76
|
self,
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
from typing import Optional, Union
|
|
2
|
+
from urllib.parse import quote
|
|
3
|
+
|
|
4
|
+
from hyperbrowser.client._request import coerce_request, dump_request
|
|
5
|
+
from hyperbrowser.models.webmcp import (
|
|
6
|
+
WebMCPInvocation,
|
|
7
|
+
WebMCPInvokeParams,
|
|
8
|
+
WebMCPInvokeResult,
|
|
9
|
+
WebMCPResultParams,
|
|
10
|
+
WebMCPStartParams,
|
|
11
|
+
WebMCPToolsResponse,
|
|
12
|
+
)
|
|
13
|
+
from hyperbrowser.types.webmcp import (
|
|
14
|
+
WebMCPInvokeParams as WebMCPInvokeParamsDict,
|
|
15
|
+
WebMCPResultParams as WebMCPResultParamsDict,
|
|
16
|
+
WebMCPStartParams as WebMCPStartParamsDict,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class WebMCPManager:
|
|
21
|
+
"""Discover and invoke page tools in sessions created with enable_web_mcp=True."""
|
|
22
|
+
|
|
23
|
+
def __init__(self, client):
|
|
24
|
+
self._client = client
|
|
25
|
+
|
|
26
|
+
def _url(self, session_id: str, suffix: str) -> str:
|
|
27
|
+
return self._client._build_url(
|
|
28
|
+
f"/session/{quote(session_id, safe='')}/webmcp{suffix}"
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
def list_tools(self, session_id: str) -> WebMCPToolsResponse:
|
|
32
|
+
"""Discover document-bound tools across the session's tabs and frames."""
|
|
33
|
+
response = self._client.transport.get(
|
|
34
|
+
self._url(session_id, "/tools"), timeout=max(self._client.timeout, 40)
|
|
35
|
+
)
|
|
36
|
+
return WebMCPToolsResponse(**response.data)
|
|
37
|
+
|
|
38
|
+
def invoke(
|
|
39
|
+
self,
|
|
40
|
+
session_id: str,
|
|
41
|
+
params: Union[WebMCPInvokeParamsDict, WebMCPInvokeParams],
|
|
42
|
+
) -> WebMCPInvokeResult:
|
|
43
|
+
"""Invoke once and wait. A form can return awaiting_submission with a handle.
|
|
44
|
+
|
|
45
|
+
This POST is never automatically retried: losing its response can leave the
|
|
46
|
+
outcome unknown, and repeating it could duplicate a side effect.
|
|
47
|
+
"""
|
|
48
|
+
request = coerce_request(params, WebMCPInvokeParams)
|
|
49
|
+
response = self._client.transport.post(
|
|
50
|
+
self._url(session_id, "/invoke"),
|
|
51
|
+
data=dump_request(request, WebMCPInvokeParams),
|
|
52
|
+
timeout=max(self._client.timeout, request.timeout_seconds + 35),
|
|
53
|
+
)
|
|
54
|
+
return WebMCPInvokeResult(**response.data)
|
|
55
|
+
|
|
56
|
+
def start(
|
|
57
|
+
self,
|
|
58
|
+
session_id: str,
|
|
59
|
+
params: Union[WebMCPStartParamsDict, WebMCPStartParams],
|
|
60
|
+
) -> WebMCPInvocation:
|
|
61
|
+
"""Start once and return a handle; use get_result to observe its outcome."""
|
|
62
|
+
response = self._client.transport.post(
|
|
63
|
+
self._url(session_id, "/invocations"),
|
|
64
|
+
data=dump_request(params, WebMCPStartParams),
|
|
65
|
+
timeout=max(self._client.timeout, 40),
|
|
66
|
+
)
|
|
67
|
+
return WebMCPInvocation(**response.data)
|
|
68
|
+
|
|
69
|
+
def get_result(
|
|
70
|
+
self,
|
|
71
|
+
session_id: str,
|
|
72
|
+
invocation_id: str,
|
|
73
|
+
params: Optional[Union[WebMCPResultParamsDict, WebMCPResultParams]] = None,
|
|
74
|
+
) -> WebMCPInvocation:
|
|
75
|
+
"""Read or long-poll once. Running/awaiting_submission can remain pending.
|
|
76
|
+
|
|
77
|
+
Handles are in memory. Terminal results expire after 10 minutes and may
|
|
78
|
+
be evicted sooner; browser shutdown or receiver restart also loses them.
|
|
79
|
+
"""
|
|
80
|
+
request = coerce_request(
|
|
81
|
+
params if params is not None else {}, WebMCPResultParams
|
|
82
|
+
)
|
|
83
|
+
response = self._client.transport.get(
|
|
84
|
+
self._url(session_id, f"/invocations/{quote(invocation_id, safe='')}"),
|
|
85
|
+
params=dump_request(request, WebMCPResultParams),
|
|
86
|
+
timeout=max(self._client.timeout, request.wait_seconds + 20),
|
|
87
|
+
)
|
|
88
|
+
return WebMCPInvocation(**response.data)
|
|
89
|
+
|
|
90
|
+
def cancel(self, session_id: str, invocation_id: str) -> WebMCPInvocation:
|
|
91
|
+
"""Request best-effort cancellation. Completion can win; side effects persist."""
|
|
92
|
+
response = self._client.transport.post(
|
|
93
|
+
self._url(
|
|
94
|
+
session_id, f"/invocations/{quote(invocation_id, safe='')}/cancel"
|
|
95
|
+
),
|
|
96
|
+
timeout=max(self._client.timeout, 20),
|
|
97
|
+
)
|
|
98
|
+
return WebMCPInvocation(**response.data)
|
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
from .webmcp import (
|
|
2
|
+
WebMCPAnnotations,
|
|
3
|
+
WebMCPFrame,
|
|
4
|
+
WebMCPSource,
|
|
5
|
+
WebMCPTool,
|
|
6
|
+
WebMCPToolsResponse,
|
|
7
|
+
WebMCPInvokeParams,
|
|
8
|
+
WebMCPStartParams,
|
|
9
|
+
WebMCPResultParams,
|
|
10
|
+
WebMCPInvokeStatus,
|
|
11
|
+
WebMCPInvocationStatus,
|
|
12
|
+
WebMCPInvokeResult,
|
|
13
|
+
WebMCPInvocationError,
|
|
14
|
+
WebMCPInvocation,
|
|
15
|
+
)
|
|
1
16
|
from .web.batch_fetch import (
|
|
2
17
|
StartBatchFetchJobParams,
|
|
3
18
|
StartBatchFetchJobResponse,
|
|
@@ -439,6 +454,20 @@ from .sandbox import (
|
|
|
439
454
|
from .team import TeamCreditInfo
|
|
440
455
|
|
|
441
456
|
__all__ = [
|
|
457
|
+
"WebMCPAnnotations",
|
|
458
|
+
"WebMCPFrame",
|
|
459
|
+
"WebMCPSource",
|
|
460
|
+
"WebMCPTool",
|
|
461
|
+
"WebMCPToolsResponse",
|
|
462
|
+
"WebMCPInvokeParams",
|
|
463
|
+
"WebMCPStartParams",
|
|
464
|
+
"WebMCPResultParams",
|
|
465
|
+
"WebMCPInvokeStatus",
|
|
466
|
+
"WebMCPInvocationStatus",
|
|
467
|
+
"WebMCPInvokeResult",
|
|
468
|
+
"WebMCPInvocationError",
|
|
469
|
+
"WebMCPInvocation",
|
|
470
|
+
|
|
442
471
|
# consts
|
|
443
472
|
"ISO639_1",
|
|
444
473
|
"POLLING_ATTEMPTS",
|
|
@@ -129,6 +129,8 @@ class SessionLaunchState(BaseModel):
|
|
|
129
129
|
populate_by_alias=True,
|
|
130
130
|
)
|
|
131
131
|
|
|
132
|
+
enable_web_mcp: Optional[bool] = Field(default=None, alias="enableWebMcp")
|
|
133
|
+
|
|
132
134
|
use_ultra_stealth: Optional[bool] = Field(default=None, alias="useUltraStealth")
|
|
133
135
|
use_stealth: Optional[bool] = Field(default=None, alias="useStealth")
|
|
134
136
|
use_proxy: Optional[bool] = Field(default=None, alias="useProxy")
|
|
@@ -411,6 +413,10 @@ class CreateSessionParams(BaseModel):
|
|
|
411
413
|
populate_by_alias=True,
|
|
412
414
|
)
|
|
413
415
|
|
|
416
|
+
enable_web_mcp: Optional[bool] = Field(
|
|
417
|
+
default=None, serialization_alias="enableWebMcp"
|
|
418
|
+
)
|
|
419
|
+
|
|
414
420
|
use_ultra_stealth: bool = Field(
|
|
415
421
|
default=False, serialization_alias="useUltraStealth"
|
|
416
422
|
)
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"""WebMCP request models and page-tool discovery/invocation responses."""
|
|
2
|
+
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
from typing import Any, Dict, List, Literal, Optional
|
|
5
|
+
|
|
6
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class WebMCPInvokeParams(BaseModel):
|
|
10
|
+
model_config = ConfigDict(populate_by_name=True, extra="forbid")
|
|
11
|
+
|
|
12
|
+
tool_ref: str = Field(min_length=1, max_length=4096, serialization_alias="toolRef")
|
|
13
|
+
input: Dict[str, Any] = Field(default_factory=dict)
|
|
14
|
+
timeout_seconds: int = Field(
|
|
15
|
+
default=60, ge=1, le=120, strict=True, serialization_alias="timeoutSeconds"
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class WebMCPStartParams(WebMCPInvokeParams):
|
|
20
|
+
timeout_seconds: int = Field(
|
|
21
|
+
default=300, ge=1, le=3600, strict=True, serialization_alias="timeoutSeconds"
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class WebMCPResultParams(BaseModel):
|
|
26
|
+
model_config = ConfigDict(populate_by_name=True, extra="forbid")
|
|
27
|
+
|
|
28
|
+
wait_seconds: int = Field(
|
|
29
|
+
default=0, ge=0, le=30, strict=True, serialization_alias="waitSeconds"
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class WebMCPAnnotations(BaseModel):
|
|
34
|
+
model_config = ConfigDict(populate_by_name=True)
|
|
35
|
+
|
|
36
|
+
read_only: bool = Field(alias="readOnly")
|
|
37
|
+
untrusted_content: bool = Field(alias="untrustedContent")
|
|
38
|
+
consequential: bool
|
|
39
|
+
autosubmit: bool
|
|
40
|
+
destructive: Optional[bool] = None
|
|
41
|
+
idempotent: Optional[bool] = None
|
|
42
|
+
open_world: Optional[bool] = Field(default=None, alias="openWorld")
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class WebMCPFrame(BaseModel):
|
|
46
|
+
model_config = ConfigDict(populate_by_name=True)
|
|
47
|
+
|
|
48
|
+
id: str
|
|
49
|
+
url: str
|
|
50
|
+
is_main_frame: bool = Field(alias="isMainFrame")
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class WebMCPSource(BaseModel):
|
|
54
|
+
model_config = ConfigDict(populate_by_name=True)
|
|
55
|
+
|
|
56
|
+
provider: Literal["native", "polyfill"]
|
|
57
|
+
tab_id: str = Field(alias="tabId")
|
|
58
|
+
page_url: str = Field(alias="pageUrl")
|
|
59
|
+
page_title: str = Field(alias="pageTitle")
|
|
60
|
+
frame: WebMCPFrame
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class WebMCPTool(BaseModel):
|
|
64
|
+
model_config = ConfigDict(populate_by_name=True)
|
|
65
|
+
|
|
66
|
+
tool_ref: str = Field(alias="toolRef")
|
|
67
|
+
name: str
|
|
68
|
+
title: Optional[str] = None
|
|
69
|
+
description: str
|
|
70
|
+
input_schema: Optional[Dict[str, Any]] = Field(default=None, alias="inputSchema")
|
|
71
|
+
output_schema: Optional[Dict[str, Any]] = Field(default=None, alias="outputSchema")
|
|
72
|
+
annotations: WebMCPAnnotations
|
|
73
|
+
declarative: bool
|
|
74
|
+
backend_node_id: Optional[int] = Field(default=None, alias="backendNodeId")
|
|
75
|
+
source: WebMCPSource
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
class WebMCPToolsResponse(BaseModel):
|
|
79
|
+
model_config = ConfigDict(populate_by_name=True)
|
|
80
|
+
|
|
81
|
+
tools: List[WebMCPTool]
|
|
82
|
+
native_supported: bool = Field(alias="nativeSupported")
|
|
83
|
+
truncated: bool
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
WebMCPInvokeStatus = Literal["completed", "error", "canceled", "awaiting_submission"]
|
|
87
|
+
WebMCPInvocationStatus = Literal[
|
|
88
|
+
"running",
|
|
89
|
+
"awaiting_submission",
|
|
90
|
+
"completed",
|
|
91
|
+
"error",
|
|
92
|
+
"canceled",
|
|
93
|
+
"outcome_unknown",
|
|
94
|
+
]
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
class WebMCPInvokeResult(BaseModel):
|
|
98
|
+
model_config = ConfigDict(populate_by_name=True)
|
|
99
|
+
|
|
100
|
+
invocation_id: Optional[str] = Field(default=None, alias="invocationId")
|
|
101
|
+
status: WebMCPInvokeStatus
|
|
102
|
+
output: Any = None
|
|
103
|
+
error_text: Optional[str] = Field(default=None, alias="errorText")
|
|
104
|
+
output_bytes: int = Field(alias="outputBytes")
|
|
105
|
+
output_truncated: bool = Field(default=False, alias="outputTruncated")
|
|
106
|
+
output_preview: Optional[str] = Field(default=None, alias="outputPreview")
|
|
107
|
+
untrusted_content: bool = Field(alias="untrustedContent")
|
|
108
|
+
duration_ms: int = Field(alias="durationMs")
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
class WebMCPInvocationError(BaseModel):
|
|
112
|
+
code: str
|
|
113
|
+
message: str
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
class WebMCPInvocation(BaseModel):
|
|
117
|
+
model_config = ConfigDict(populate_by_name=True)
|
|
118
|
+
|
|
119
|
+
invocation_id: str = Field(alias="invocationId")
|
|
120
|
+
tool_ref: str = Field(alias="toolRef")
|
|
121
|
+
status: WebMCPInvocationStatus
|
|
122
|
+
cancellation_requested: bool = Field(alias="cancellationRequested")
|
|
123
|
+
created_at: datetime = Field(alias="createdAt")
|
|
124
|
+
expires_at: Optional[datetime] = Field(default=None, alias="expiresAt")
|
|
125
|
+
result: Optional[WebMCPInvokeResult] = None
|
|
126
|
+
error: Optional[WebMCPInvocationError] = None
|
|
@@ -64,6 +64,7 @@ class AsyncTransport(TransportStrategy):
|
|
|
64
64
|
)
|
|
65
65
|
return APIResponse.from_status(response.status_code)
|
|
66
66
|
except httpx.HTTPStatusError as e:
|
|
67
|
+
error_data = None
|
|
67
68
|
try:
|
|
68
69
|
error_data = response.json()
|
|
69
70
|
message = error_data.get("message") or error_data.get("error") or str(e)
|
|
@@ -71,6 +72,13 @@ class AsyncTransport(TransportStrategy):
|
|
|
71
72
|
message = str(e)
|
|
72
73
|
raise HyperbrowserError(
|
|
73
74
|
message,
|
|
75
|
+
code=(
|
|
76
|
+
error_data.get("code")
|
|
77
|
+
if isinstance(error_data, dict)
|
|
78
|
+
and isinstance(error_data.get("code"), str)
|
|
79
|
+
else None
|
|
80
|
+
),
|
|
81
|
+
details=error_data,
|
|
74
82
|
status_code=response.status_code,
|
|
75
83
|
response=response,
|
|
76
84
|
original_error=e,
|
|
@@ -108,15 +116,23 @@ class AsyncTransport(TransportStrategy):
|
|
|
108
116
|
)
|
|
109
117
|
|
|
110
118
|
async def get(
|
|
111
|
-
self,
|
|
119
|
+
self,
|
|
120
|
+
url: str,
|
|
121
|
+
params: Optional[dict] = None,
|
|
122
|
+
follow_redirects: bool = False,
|
|
123
|
+
*,
|
|
124
|
+
timeout: Optional[float] = None,
|
|
112
125
|
) -> APIResponse:
|
|
113
126
|
if params:
|
|
114
127
|
params = {k: v for k, v in params.items() if v is not None}
|
|
128
|
+
kwargs = {}
|
|
129
|
+
if timeout is not None:
|
|
130
|
+
kwargs["timeout"] = timeout
|
|
115
131
|
failed_attempt = 1
|
|
116
132
|
while True:
|
|
117
133
|
try:
|
|
118
134
|
response = await self.client.get(
|
|
119
|
-
url, params=params, follow_redirects=follow_redirects
|
|
135
|
+
url, params=params, follow_redirects=follow_redirects, **kwargs
|
|
120
136
|
)
|
|
121
137
|
return await self._handle_response(response)
|
|
122
138
|
except BaseException as cause:
|
|
@@ -55,7 +55,14 @@ class TransportStrategy(ABC):
|
|
|
55
55
|
pass
|
|
56
56
|
|
|
57
57
|
@abstractmethod
|
|
58
|
-
def get(
|
|
58
|
+
def get(
|
|
59
|
+
self,
|
|
60
|
+
url: str,
|
|
61
|
+
params: Optional[dict] = None,
|
|
62
|
+
follow_redirects: bool = False,
|
|
63
|
+
*,
|
|
64
|
+
timeout: Optional[float] = None,
|
|
65
|
+
) -> APIResponse:
|
|
59
66
|
pass
|
|
60
67
|
|
|
61
68
|
@abstractmethod
|
|
@@ -42,6 +42,7 @@ class SyncTransport(TransportStrategy):
|
|
|
42
42
|
)
|
|
43
43
|
return APIResponse.from_status(response.status_code)
|
|
44
44
|
except httpx.HTTPStatusError as e:
|
|
45
|
+
error_data = None
|
|
45
46
|
try:
|
|
46
47
|
error_data = response.json()
|
|
47
48
|
message = error_data.get("message") or error_data.get("error") or str(e)
|
|
@@ -49,6 +50,13 @@ class SyncTransport(TransportStrategy):
|
|
|
49
50
|
message = str(e)
|
|
50
51
|
raise HyperbrowserError(
|
|
51
52
|
message,
|
|
53
|
+
code=(
|
|
54
|
+
error_data.get("code")
|
|
55
|
+
if isinstance(error_data, dict)
|
|
56
|
+
and isinstance(error_data.get("code"), str)
|
|
57
|
+
else None
|
|
58
|
+
),
|
|
59
|
+
details=error_data,
|
|
52
60
|
status_code=response.status_code,
|
|
53
61
|
response=response,
|
|
54
62
|
original_error=e,
|
|
@@ -89,15 +97,23 @@ class SyncTransport(TransportStrategy):
|
|
|
89
97
|
)
|
|
90
98
|
|
|
91
99
|
def get(
|
|
92
|
-
self,
|
|
100
|
+
self,
|
|
101
|
+
url: str,
|
|
102
|
+
params: Optional[dict] = None,
|
|
103
|
+
follow_redirects: bool = False,
|
|
104
|
+
*,
|
|
105
|
+
timeout: Optional[float] = None,
|
|
93
106
|
) -> APIResponse:
|
|
94
107
|
if params:
|
|
95
108
|
params = {k: v for k, v in params.items() if v is not None}
|
|
109
|
+
kwargs = {}
|
|
110
|
+
if timeout is not None:
|
|
111
|
+
kwargs["timeout"] = timeout
|
|
96
112
|
failed_attempt = 1
|
|
97
113
|
while True:
|
|
98
114
|
try:
|
|
99
115
|
response = self.client.get(
|
|
100
|
-
url, params=params, follow_redirects=follow_redirects
|
|
116
|
+
url, params=params, follow_redirects=follow_redirects, **kwargs
|
|
101
117
|
)
|
|
102
118
|
return self._handle_response(response)
|
|
103
119
|
except BaseException as cause:
|
|
@@ -5,6 +5,11 @@ known request keys to their wire aliases while leaving user-owned mappings, such
|
|
|
5
5
|
as JSON Schema objects, untouched.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
+
from .webmcp import (
|
|
9
|
+
WebMCPInvokeParams,
|
|
10
|
+
WebMCPStartParams,
|
|
11
|
+
WebMCPResultParams,
|
|
12
|
+
)
|
|
8
13
|
from ._json import (
|
|
9
14
|
JSONSchema,
|
|
10
15
|
JSONSchemaInput,
|
|
@@ -178,6 +183,10 @@ from .web import (
|
|
|
178
183
|
|
|
179
184
|
|
|
180
185
|
__all__ = [
|
|
186
|
+
"WebMCPInvokeParams",
|
|
187
|
+
"WebMCPStartParams",
|
|
188
|
+
"WebMCPResultParams",
|
|
189
|
+
|
|
181
190
|
"JSONSchema",
|
|
182
191
|
"JSONSchemaInput",
|
|
183
192
|
"JSONSchemaObject",
|
|
@@ -117,6 +117,7 @@ class StartSessionFromSnapshotParams(TypedDict):
|
|
|
117
117
|
class CreateSessionParams(TypedDict, total=False):
|
|
118
118
|
"""Configuration for creating a browser session."""
|
|
119
119
|
|
|
120
|
+
enable_web_mcp: Optional[bool]
|
|
120
121
|
use_ultra_stealth: bool
|
|
121
122
|
use_stealth: bool
|
|
122
123
|
use_proxy: bool
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""Typed dictionary requests for session WebMCP tools."""
|
|
2
|
+
|
|
3
|
+
from typing import Any, Dict
|
|
4
|
+
from typing_extensions import Required, TypedDict
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class WebMCPInvokeParams(TypedDict, total=False):
|
|
8
|
+
"""Blocking invocation; timeout_seconds is 1–120 (default 60)."""
|
|
9
|
+
|
|
10
|
+
tool_ref: Required[str]
|
|
11
|
+
input: Dict[str, Any]
|
|
12
|
+
timeout_seconds: int
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class WebMCPStartParams(WebMCPInvokeParams):
|
|
16
|
+
"""Start an invocation; timeout_seconds is 1–3600 (default 300)."""
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class WebMCPResultParams(TypedDict, total=False):
|
|
20
|
+
"""Wait at most 0–30 seconds (default 0) for an invocation result."""
|
|
21
|
+
|
|
22
|
+
wait_seconds: int
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/async_manager/agents/cua.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/async_manager/crawl.py
RENAMED
|
File without changes
|
{hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/async_manager/extension.py
RENAMED
|
File without changes
|
{hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/async_manager/extract.py
RENAMED
|
File without changes
|
{hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/async_manager/profile.py
RENAMED
|
File without changes
|
{hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/async_manager/sandbox.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/async_manager/scrape.py
RENAMED
|
File without changes
|
{hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/async_manager/team.py
RENAMED
|
File without changes
|
{hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/async_manager/volume.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/async_manager/web/crawl.py
RENAMED
|
File without changes
|
{hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sandboxes/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sandboxes/dockerignore.py
RENAMED
|
File without changes
|
{hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sandboxes/image_build.py
RENAMED
|
File without changes
|
|
File without changes
|
{hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sandboxes/process_output.py
RENAMED
|
File without changes
|
{hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sandboxes/shared.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sync_manager/agents/cua.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sync_manager/crawl.py
RENAMED
|
File without changes
|
{hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sync_manager/extension.py
RENAMED
|
File without changes
|
{hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sync_manager/extract.py
RENAMED
|
File without changes
|
{hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sync_manager/profile.py
RENAMED
|
File without changes
|
{hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sync_manager/sandbox.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sync_manager/scrape.py
RENAMED
|
File without changes
|
{hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sync_manager/team.py
RENAMED
|
File without changes
|
{hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sync_manager/volume.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/client/managers/sync_manager/web/crawl.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/models/agents/claude_computer_use.py
RENAMED
|
File without changes
|
|
File without changes
|
{hyperbrowser-1.10.0 → hyperbrowser-1.11.0}/hyperbrowser/models/agents/gemini_computer_use.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|