hyperbrowser 1.2.3__tar.gz → 1.4.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.2.3 → hyperbrowser-1.4.0}/PKG-INFO +2 -1
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/README.md +1 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/async_manager/sandbox.py +235 -37
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/async_manager/sandboxes/sandbox_transport.py +4 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/async_manager/volume.py +8 -0
- hyperbrowser-1.4.0/hyperbrowser/client/managers/sandboxes/dockerfile_analysis.py +293 -0
- hyperbrowser-1.4.0/hyperbrowser/client/managers/sandboxes/dockerignore.py +254 -0
- hyperbrowser-1.4.0/hyperbrowser/client/managers/sandboxes/image_build.py +1484 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/sync_manager/sandbox.py +228 -36
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/sync_manager/sandboxes/sandbox_transport.py +4 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/sync_manager/volume.py +8 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/models/__init__.py +22 -1
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/models/sandbox.py +81 -2
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/models/volume.py +6 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/sandbox_common.py +64 -1
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/transport/async_transport.py +43 -14
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/transport/sync.py +45 -14
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/types/__init__.py +12 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/types/sandbox.py +64 -1
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/pyproject.toml +1 -1
- hyperbrowser-1.2.3/hyperbrowser/client/managers/sandboxes/image_build.py +0 -375
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/LICENSE +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/__init__.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/_request.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/async_client.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/base.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/async_manager/agents/__init__.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/async_manager/agents/browser_use.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/async_manager/agents/claude_computer_use.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/async_manager/agents/cua.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/async_manager/agents/gemini_computer_use.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/async_manager/agents/grok_computer_use.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/async_manager/agents/hyper_agent.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/async_manager/computer_action.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/async_manager/crawl.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/async_manager/extension.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/async_manager/extract.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/async_manager/profile.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/async_manager/sandboxes/__init__.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/async_manager/sandboxes/sandbox_files.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/async_manager/sandboxes/sandbox_processes.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/async_manager/sandboxes/sandbox_terminal.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/async_manager/scrape.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/async_manager/session.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/async_manager/team.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/async_manager/web/__init__.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/async_manager/web/batch_fetch.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/async_manager/web/crawl.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/sandboxes/__init__.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/sandboxes/shared.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/sync_manager/agents/__init__.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/sync_manager/agents/browser_use.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/sync_manager/agents/claude_computer_use.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/sync_manager/agents/cua.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/sync_manager/agents/gemini_computer_use.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/sync_manager/agents/grok_computer_use.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/sync_manager/agents/hyper_agent.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/sync_manager/computer_action.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/sync_manager/crawl.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/sync_manager/extension.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/sync_manager/extract.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/sync_manager/profile.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/sync_manager/sandboxes/__init__.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/sync_manager/sandboxes/sandbox_files.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/sync_manager/sandboxes/sandbox_processes.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/sync_manager/sandboxes/sandbox_terminal.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/sync_manager/scrape.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/sync_manager/session.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/sync_manager/team.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/sync_manager/web/__init__.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/sync_manager/web/batch_fetch.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/sync_manager/web/crawl.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/sync.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/config.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/exceptions.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/models/_parsers.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/models/agents/browser_use.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/models/agents/claude_computer_use.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/models/agents/cua.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/models/agents/gemini_computer_use.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/models/agents/grok_computer_use.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/models/agents/hyper_agent.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/models/computer_action.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/models/consts.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/models/crawl.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/models/extension.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/models/extract.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/models/profile.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/models/scrape.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/models/session.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/models/team.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/models/web/batch_fetch.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/models/web/branding.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/models/web/common.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/models/web/crawl.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/models/web/fetch.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/models/web/search.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/py.typed +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/tools/__init__.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/tools/anthropic.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/tools/openai.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/tools/schema.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/transport/base.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/types/_json.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/types/agents.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/types/computer_action.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/types/crawl.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/types/extension.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/types/extract.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/types/profile.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/types/scrape.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/types/session.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/types/volume.py +0 -0
- {hyperbrowser-1.2.3 → hyperbrowser-1.4.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.4.0
|
|
4
4
|
Summary: Python SDK for hyperbrowser
|
|
5
5
|
License: MIT
|
|
6
6
|
License-File: LICENSE
|
|
@@ -250,6 +250,7 @@ sandbox = client.sandboxes.create(
|
|
|
250
250
|
)
|
|
251
251
|
|
|
252
252
|
sandbox.stop()
|
|
253
|
+
client.volumes.delete(same_volume.id)
|
|
253
254
|
client.close()
|
|
254
255
|
```
|
|
255
256
|
|
{hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/async_manager/sandbox.py
RENAMED
|
@@ -9,12 +9,14 @@ from ....models.sandbox import (
|
|
|
9
9
|
CompleteSandboxImageBuildParams,
|
|
10
10
|
CreateSandboxParams,
|
|
11
11
|
CreateSandboxImageBuildParams,
|
|
12
|
+
ReuseSandboxDockerImageParams,
|
|
12
13
|
SandboxDetail,
|
|
13
14
|
SandboxExecParams,
|
|
14
15
|
SandboxExposeParams,
|
|
15
16
|
SandboxExposeResult,
|
|
16
17
|
SandboxImageBuild,
|
|
17
18
|
SandboxImageBuildCreateResult,
|
|
19
|
+
SandboxDockerImageReuseResult,
|
|
18
20
|
SandboxImageBuildListParams,
|
|
19
21
|
SandboxImageBuildListResponse,
|
|
20
22
|
SandboxImageListParams,
|
|
@@ -39,6 +41,7 @@ from ....models.session import BasicResponse
|
|
|
39
41
|
from ....types import (
|
|
40
42
|
CompleteSandboxImageBuildParams as CompleteSandboxImageBuildParamsDict,
|
|
41
43
|
CreateSandboxImageBuildParams as CreateSandboxImageBuildParamsDict,
|
|
44
|
+
ReuseSandboxDockerImageParams as ReuseSandboxDockerImageParamsDict,
|
|
42
45
|
CreateSandboxParams as CreateSandboxParamsDict,
|
|
43
46
|
SandboxExecParams as SandboxExecParamsDict,
|
|
44
47
|
SandboxExposeParams as SandboxExposeParamsDict,
|
|
@@ -54,8 +57,11 @@ from ....types import (
|
|
|
54
57
|
from ....sandbox_common import (
|
|
55
58
|
RuntimeConnection,
|
|
56
59
|
ensure_response_ok,
|
|
60
|
+
get_retry_delay_seconds,
|
|
57
61
|
normalize_network_error,
|
|
62
|
+
request_context,
|
|
58
63
|
parse_json_response,
|
|
64
|
+
should_retry_get,
|
|
59
65
|
)
|
|
60
66
|
from ..sandboxes.shared import (
|
|
61
67
|
_build_sandbox_exposed_url,
|
|
@@ -67,9 +73,12 @@ from ..sandboxes.image_build import (
|
|
|
67
73
|
build_docker_image_from_dockerfile,
|
|
68
74
|
is_terminal_image_build_status,
|
|
69
75
|
make_temp_docker_tag,
|
|
70
|
-
|
|
76
|
+
merge_image_init,
|
|
77
|
+
package_docker_build_context_manifest,
|
|
78
|
+
package_docker_image_manifest,
|
|
79
|
+
prepare_docker_image_manifest_source,
|
|
71
80
|
remove_docker_image,
|
|
72
|
-
|
|
81
|
+
upload_missing_image_build_artifacts,
|
|
73
82
|
)
|
|
74
83
|
from .sandboxes.sandbox_files import (
|
|
75
84
|
DEFAULT_WATCH_TIMEOUT_MS,
|
|
@@ -494,6 +503,20 @@ class SandboxManager:
|
|
|
494
503
|
payload = await self._request("GET", f"/images/builds/{build_id}")
|
|
495
504
|
return SandboxImageBuild(**payload["build"])
|
|
496
505
|
|
|
506
|
+
async def reuse_docker_image(
|
|
507
|
+
self,
|
|
508
|
+
params: Union[
|
|
509
|
+
ReuseSandboxDockerImageParamsDict,
|
|
510
|
+
ReuseSandboxDockerImageParams,
|
|
511
|
+
],
|
|
512
|
+
) -> SandboxDockerImageReuseResult:
|
|
513
|
+
payload = await self._request(
|
|
514
|
+
"POST",
|
|
515
|
+
"/images/builds/reuse",
|
|
516
|
+
data=dump_request(params, ReuseSandboxDockerImageParams),
|
|
517
|
+
)
|
|
518
|
+
return SandboxDockerImageReuseResult(**payload)
|
|
519
|
+
|
|
497
520
|
async def complete_image_build(
|
|
498
521
|
self,
|
|
499
522
|
build_id: str,
|
|
@@ -566,18 +589,158 @@ class SandboxManager:
|
|
|
566
589
|
temp_dir: Optional[str] = None,
|
|
567
590
|
upload_timeout: Optional[float] = None,
|
|
568
591
|
) -> SandboxImageBuild:
|
|
569
|
-
|
|
570
|
-
|
|
592
|
+
source = await _run_blocking(
|
|
593
|
+
prepare_docker_image_manifest_source,
|
|
571
594
|
docker_image,
|
|
572
595
|
platform=platform,
|
|
596
|
+
)
|
|
597
|
+
try:
|
|
598
|
+
explicit_image_init = (
|
|
599
|
+
coerce_request(image_init, SandboxImageInit, name="image_init")
|
|
600
|
+
if image_init is not None
|
|
601
|
+
else None
|
|
602
|
+
)
|
|
603
|
+
normalized_image_init = merge_image_init(
|
|
604
|
+
source.image_init,
|
|
605
|
+
explicit_image_init,
|
|
606
|
+
)
|
|
607
|
+
normalized_image_config_user = (
|
|
608
|
+
image_config_user
|
|
609
|
+
if image_config_user is not None
|
|
610
|
+
else source.image_config_user
|
|
611
|
+
)
|
|
612
|
+
try:
|
|
613
|
+
reused = await self.reuse_docker_image(
|
|
614
|
+
ReuseSandboxDockerImageParams(
|
|
615
|
+
image_name=image_name,
|
|
616
|
+
source_image_digest=source.image_digest,
|
|
617
|
+
source_platform=platform,
|
|
618
|
+
image_config_user=normalized_image_config_user,
|
|
619
|
+
image_init=normalized_image_init,
|
|
620
|
+
)
|
|
621
|
+
)
|
|
622
|
+
except HyperbrowserError as error:
|
|
623
|
+
if error.status_code != 404:
|
|
624
|
+
raise
|
|
625
|
+
reused = None
|
|
626
|
+
if reused is not None and reused.hit:
|
|
627
|
+
if reused.build is None:
|
|
628
|
+
raise RuntimeError(
|
|
629
|
+
"exact image cache response is missing its completed build"
|
|
630
|
+
)
|
|
631
|
+
return reused.build
|
|
632
|
+
|
|
633
|
+
packaged = await _run_blocking(
|
|
634
|
+
package_docker_image_manifest,
|
|
635
|
+
docker_image,
|
|
636
|
+
source.image_digest,
|
|
637
|
+
source.config,
|
|
638
|
+
platform=platform,
|
|
639
|
+
temp_dir=temp_dir,
|
|
640
|
+
)
|
|
641
|
+
build_id = None
|
|
642
|
+
build_started = False
|
|
643
|
+
try:
|
|
644
|
+
artifact = packaged.artifact
|
|
645
|
+
create_result = await self.create_image_build(
|
|
646
|
+
CreateSandboxImageBuildParams(
|
|
647
|
+
image_name=image_name,
|
|
648
|
+
input_sha256=artifact.sha256_hex,
|
|
649
|
+
input_size_bytes=artifact.size_bytes,
|
|
650
|
+
input_format=artifact.input_format,
|
|
651
|
+
source_platform=artifact.source_platform,
|
|
652
|
+
image_config_user=normalized_image_config_user,
|
|
653
|
+
image_init=normalized_image_init,
|
|
654
|
+
docker_image_manifest=packaged.manifest,
|
|
655
|
+
)
|
|
656
|
+
)
|
|
657
|
+
build_id = create_result.build.id
|
|
658
|
+
await _run_blocking(
|
|
659
|
+
upload_missing_image_build_artifacts,
|
|
660
|
+
create_result.uploads,
|
|
661
|
+
packaged.layers,
|
|
662
|
+
label="Docker image layer",
|
|
663
|
+
timeout=upload_timeout,
|
|
664
|
+
)
|
|
665
|
+
build = await self._complete_image_build_resilient(
|
|
666
|
+
build_id,
|
|
667
|
+
artifact,
|
|
668
|
+
)
|
|
669
|
+
build_started = True
|
|
670
|
+
if wait:
|
|
671
|
+
return await self.wait_for_image_build(
|
|
672
|
+
build.id,
|
|
673
|
+
poll_interval=poll_interval,
|
|
674
|
+
timeout=wait_timeout,
|
|
675
|
+
)
|
|
676
|
+
return build
|
|
677
|
+
except Exception:
|
|
678
|
+
if build_id is not None and not build_started:
|
|
679
|
+
try:
|
|
680
|
+
await self.cancel_image_build(build_id)
|
|
681
|
+
except Exception:
|
|
682
|
+
pass
|
|
683
|
+
raise
|
|
684
|
+
finally:
|
|
685
|
+
await _run_blocking(packaged.cleanup)
|
|
686
|
+
finally:
|
|
687
|
+
await _run_blocking(source.cleanup)
|
|
688
|
+
|
|
689
|
+
async def _complete_image_build_resilient(
|
|
690
|
+
self,
|
|
691
|
+
build_id: str,
|
|
692
|
+
artifact,
|
|
693
|
+
) -> SandboxImageBuild:
|
|
694
|
+
params = CompleteSandboxImageBuildParams(
|
|
695
|
+
input_sha256=artifact.sha256_hex,
|
|
696
|
+
input_size_bytes=artifact.size_bytes,
|
|
697
|
+
input_format=artifact.input_format,
|
|
698
|
+
)
|
|
699
|
+
try:
|
|
700
|
+
return await self.complete_image_build(build_id, params)
|
|
701
|
+
except HyperbrowserError as exc:
|
|
702
|
+
if exc.status_code != 409:
|
|
703
|
+
raise
|
|
704
|
+
if "already in progress" in str(exc).lower():
|
|
705
|
+
return await self.get_image_build(build_id)
|
|
706
|
+
current = await self.get_image_build(build_id)
|
|
707
|
+
if current.status not in ("awaiting_upload", "upload_verified"):
|
|
708
|
+
raise
|
|
709
|
+
await asyncio.sleep(2)
|
|
710
|
+
return await self.complete_image_build(build_id, params)
|
|
711
|
+
|
|
712
|
+
async def _build_image_from_remote_dockerfile(
|
|
713
|
+
self,
|
|
714
|
+
*,
|
|
715
|
+
context_path,
|
|
716
|
+
image_name: str,
|
|
717
|
+
dockerfile,
|
|
718
|
+
platform: str,
|
|
719
|
+
remote_full_context: bool,
|
|
720
|
+
image_init: Optional[Union[SandboxImageInitDict, SandboxImageInit]],
|
|
721
|
+
image_config_user: Optional[str],
|
|
722
|
+
wait: bool,
|
|
723
|
+
poll_interval: float,
|
|
724
|
+
wait_timeout: Optional[float],
|
|
725
|
+
temp_dir: Optional[str],
|
|
726
|
+
upload_timeout: Optional[float],
|
|
727
|
+
) -> SandboxImageBuild:
|
|
728
|
+
packaged = await _run_blocking(
|
|
729
|
+
package_docker_build_context_manifest,
|
|
730
|
+
context_path,
|
|
731
|
+
dockerfile=dockerfile,
|
|
732
|
+
force_full_context=remote_full_context,
|
|
573
733
|
temp_dir=temp_dir,
|
|
574
734
|
)
|
|
735
|
+
build_id = None
|
|
736
|
+
build_started = False
|
|
575
737
|
try:
|
|
576
738
|
normalized_image_init = (
|
|
577
739
|
coerce_request(image_init, SandboxImageInit, name="image_init")
|
|
578
740
|
if image_init is not None
|
|
579
|
-
else
|
|
741
|
+
else None
|
|
580
742
|
)
|
|
743
|
+
artifact = packaged.artifact
|
|
581
744
|
create_result = await self.create_image_build(
|
|
582
745
|
CreateSandboxImageBuildParams(
|
|
583
746
|
image_name=image_name,
|
|
@@ -585,28 +748,22 @@ class SandboxManager:
|
|
|
585
748
|
input_size_bytes=artifact.size_bytes,
|
|
586
749
|
input_format=artifact.input_format,
|
|
587
750
|
source_platform=artifact.source_platform,
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
if image_config_user is not None
|
|
591
|
-
else artifact.image_config_user
|
|
592
|
-
),
|
|
751
|
+
dockerfile_path=packaged.manifest.dockerfile_path,
|
|
752
|
+
image_config_user=image_config_user,
|
|
593
753
|
image_init=normalized_image_init,
|
|
754
|
+
context_manifest=packaged.manifest,
|
|
594
755
|
)
|
|
595
756
|
)
|
|
757
|
+
build_id = create_result.build.id
|
|
596
758
|
await _run_blocking(
|
|
597
|
-
|
|
598
|
-
create_result.
|
|
599
|
-
|
|
759
|
+
upload_missing_image_build_artifacts,
|
|
760
|
+
create_result.uploads,
|
|
761
|
+
packaged.bundles,
|
|
762
|
+
label="build context bundle",
|
|
600
763
|
timeout=upload_timeout,
|
|
601
764
|
)
|
|
602
|
-
build = await self.
|
|
603
|
-
|
|
604
|
-
CompleteSandboxImageBuildParams(
|
|
605
|
-
input_sha256=artifact.sha256_hex,
|
|
606
|
-
input_size_bytes=artifact.size_bytes,
|
|
607
|
-
input_format=artifact.input_format,
|
|
608
|
-
),
|
|
609
|
-
)
|
|
765
|
+
build = await self._complete_image_build_resilient(build_id, artifact)
|
|
766
|
+
build_started = True
|
|
610
767
|
if wait:
|
|
611
768
|
return await self.wait_for_image_build(
|
|
612
769
|
build.id,
|
|
@@ -614,8 +771,15 @@ class SandboxManager:
|
|
|
614
771
|
timeout=wait_timeout,
|
|
615
772
|
)
|
|
616
773
|
return build
|
|
774
|
+
except Exception:
|
|
775
|
+
if build_id is not None and not build_started:
|
|
776
|
+
try:
|
|
777
|
+
await self.cancel_image_build(build_id)
|
|
778
|
+
except Exception:
|
|
779
|
+
pass
|
|
780
|
+
raise
|
|
617
781
|
finally:
|
|
618
|
-
|
|
782
|
+
await _run_blocking(packaged.cleanup)
|
|
619
783
|
|
|
620
784
|
async def build_image_from_dockerfile(
|
|
621
785
|
self,
|
|
@@ -623,6 +787,8 @@ class SandboxManager:
|
|
|
623
787
|
context_path,
|
|
624
788
|
image_name: str,
|
|
625
789
|
dockerfile="Dockerfile",
|
|
790
|
+
remote: bool = True,
|
|
791
|
+
remote_full_context: bool = False,
|
|
626
792
|
docker_tag: Optional[str] = None,
|
|
627
793
|
platform: str = IMAGE_BUILD_SOURCE_PLATFORM,
|
|
628
794
|
build_args: Optional[Dict[str, str]] = None,
|
|
@@ -634,6 +800,26 @@ class SandboxManager:
|
|
|
634
800
|
temp_dir: Optional[str] = None,
|
|
635
801
|
upload_timeout: Optional[float] = None,
|
|
636
802
|
) -> SandboxImageBuild:
|
|
803
|
+
if remote:
|
|
804
|
+
if docker_tag is not None or build_args:
|
|
805
|
+
raise ValueError(
|
|
806
|
+
"docker_tag and build_args require remote=False; remote "
|
|
807
|
+
"Dockerfile builds send the build context to Hyperbrowser"
|
|
808
|
+
)
|
|
809
|
+
return await self._build_image_from_remote_dockerfile(
|
|
810
|
+
context_path=context_path,
|
|
811
|
+
image_name=image_name,
|
|
812
|
+
dockerfile=dockerfile,
|
|
813
|
+
platform=platform,
|
|
814
|
+
remote_full_context=remote_full_context,
|
|
815
|
+
image_init=image_init,
|
|
816
|
+
image_config_user=image_config_user,
|
|
817
|
+
wait=wait,
|
|
818
|
+
poll_interval=poll_interval,
|
|
819
|
+
wait_timeout=wait_timeout,
|
|
820
|
+
temp_dir=temp_dir,
|
|
821
|
+
upload_timeout=upload_timeout,
|
|
822
|
+
)
|
|
637
823
|
tag = docker_tag or make_temp_docker_tag()
|
|
638
824
|
remove_tag = docker_tag is None
|
|
639
825
|
try:
|
|
@@ -759,19 +945,31 @@ class SandboxManager:
|
|
|
759
945
|
params: Optional[Dict[str, object]] = None,
|
|
760
946
|
data: Optional[Dict[str, object]] = None,
|
|
761
947
|
):
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
self._client.
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
948
|
+
failed_attempt = 1
|
|
949
|
+
while True:
|
|
950
|
+
try:
|
|
951
|
+
response = await self._client.transport.client.request(
|
|
952
|
+
method,
|
|
953
|
+
self._client._build_url(path),
|
|
954
|
+
params={
|
|
955
|
+
key: value
|
|
956
|
+
for key, value in (params or {}).items()
|
|
957
|
+
if value is not None
|
|
958
|
+
},
|
|
959
|
+
json=data,
|
|
960
|
+
)
|
|
961
|
+
ensure_response_ok(response, "control")
|
|
962
|
+
except BaseException as cause:
|
|
963
|
+
error = normalize_network_error(
|
|
964
|
+
cause,
|
|
965
|
+
"control",
|
|
966
|
+
"Unknown error occurred",
|
|
967
|
+
request_context(method, path),
|
|
968
|
+
)
|
|
969
|
+
if not should_retry_get(method, error, failed_attempt):
|
|
970
|
+
raise error
|
|
971
|
+
await asyncio.sleep(get_retry_delay_seconds(failed_attempt))
|
|
972
|
+
failed_attempt += 1
|
|
973
|
+
continue
|
|
775
974
|
|
|
776
|
-
|
|
777
|
-
return parse_json_response(response, "control")
|
|
975
|
+
return parse_json_response(response, "control")
|
|
@@ -9,6 +9,7 @@ from .....sandbox_common import (
|
|
|
9
9
|
ensure_response_ok,
|
|
10
10
|
normalize_network_error,
|
|
11
11
|
parse_json_response,
|
|
12
|
+
request_context,
|
|
12
13
|
resolve_runtime_transport_target,
|
|
13
14
|
)
|
|
14
15
|
from ...sandboxes.shared import _build_query_path, _is_replayable_http_content
|
|
@@ -275,6 +276,7 @@ class RuntimeTransport:
|
|
|
275
276
|
error,
|
|
276
277
|
"runtime",
|
|
277
278
|
"Unknown runtime request error",
|
|
279
|
+
request_context(method, path),
|
|
278
280
|
)
|
|
279
281
|
|
|
280
282
|
await response.aread()
|
|
@@ -309,6 +311,7 @@ class RuntimeTransport:
|
|
|
309
311
|
error,
|
|
310
312
|
"runtime",
|
|
311
313
|
"Unknown runtime request error",
|
|
314
|
+
request_context(method, path),
|
|
312
315
|
)
|
|
313
316
|
|
|
314
317
|
async def _send_stream(
|
|
@@ -341,4 +344,5 @@ class RuntimeTransport:
|
|
|
341
344
|
error,
|
|
342
345
|
"runtime",
|
|
343
346
|
"Unknown runtime request error",
|
|
347
|
+
request_context("GET", path),
|
|
344
348
|
)
|
{hyperbrowser-1.2.3 → hyperbrowser-1.4.0}/hyperbrowser/client/managers/async_manager/volume.py
RENAMED
|
@@ -4,6 +4,7 @@ from hyperbrowser.client._request import dump_request
|
|
|
4
4
|
from hyperbrowser.models.volume import (
|
|
5
5
|
CreateVolumeParams,
|
|
6
6
|
Volume,
|
|
7
|
+
VolumeDeleteResult,
|
|
7
8
|
VolumeListParams,
|
|
8
9
|
VolumeListResponse,
|
|
9
10
|
)
|
|
@@ -43,3 +44,10 @@ class VolumeManager:
|
|
|
43
44
|
self._client._build_url(f"/volume/{volume_id}")
|
|
44
45
|
)
|
|
45
46
|
return Volume(**response.data)
|
|
47
|
+
|
|
48
|
+
async def delete(self, volume_id: str) -> VolumeDeleteResult:
|
|
49
|
+
"""Delete a volume by id or name. Ambiguous names and active mounts return 409."""
|
|
50
|
+
response = await self._client.transport.delete(
|
|
51
|
+
self._client._build_url(f"/volume/{volume_id}")
|
|
52
|
+
)
|
|
53
|
+
return VolumeDeleteResult(**response.data)
|