agent-sandbox-harbor 0.0.3__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.
@@ -0,0 +1,110 @@
1
+ Metadata-Version: 2.4
2
+ Name: agent-sandbox-harbor
3
+ Version: 0.0.3
4
+ Summary: Agent Sandbox plugin for Harbor — run Terminal-Bench / SWE-bench / Harbor benchmarks on Agent Sandbox pools
5
+ License: Apache-2.0
6
+ Project-URL: Homepage, https://github.com/scitix/agent-sandbox
7
+ Project-URL: Source, https://github.com/scitix/agent-sandbox/tree/main/sdk/python/harbor
8
+ Requires-Python: >=3.12
9
+ Description-Content-Type: text/markdown
10
+ Requires-Dist: agent-sandbox-e2b>=0.0.2
11
+ Provides-Extra: harbor
12
+ Requires-Dist: harbor<=0.7.1,>=0.7.0; extra == "harbor"
13
+ Requires-Dist: e2b>=2.0.0; extra == "harbor"
14
+ Provides-Extra: dev
15
+ Requires-Dist: harbor>=0.7.0; extra == "dev"
16
+ Requires-Dist: e2b>=2.0.0; extra == "dev"
17
+ Requires-Dist: ruff>=0.4.0; extra == "dev"
18
+
19
+ # agent-sandbox-harbor
20
+
21
+ A [Harbor](https://github.com/harbor-framework/harbor) environment plugin that runs Harbor
22
+ benchmarks (Terminal-Bench, SWE-bench, custom datasets) on
23
+ [Agent Sandbox](https://github.com/scitix/agent-sandbox) pre-warmed pools — no fork of Harbor
24
+ required.
25
+
26
+ Highlights:
27
+
28
+ - **Zero Harbor source changes.** Plugs into Harbor via the official
29
+ `--environment-import-path` extension point.
30
+ - **Skips Template Build.** Agent Sandbox uses a pre-warmed Pod pool with in-place image swap,
31
+ so the per-task Template Build step that E2B / Novita require is replaced by a single
32
+ `POST /v1/sandboxes` call.
33
+ - **Internal-mirror friendly.** A configurable image-prefix rewrites `docker.io/...` to your
34
+ private Distribution / Harbor registry.
35
+
36
+ ## Installation
37
+
38
+ ```bash
39
+ pip install 'harbor[e2b]' agent-sandbox-harbor
40
+ ```
41
+
42
+ The plugin pulls [`agent-sandbox-e2b`](https://pypi.org/project/agent-sandbox-e2b/) as a hard
43
+ dependency (it calls `patch_e2b()` at import). `harbor` is an optional peer dependency, so the
44
+ package can be inspected / unit-tested without it; in real usage you install `harbor[e2b]`
45
+ yourself.
46
+
47
+ ## Quick start
48
+
49
+ ```bash
50
+ # 1. Set credentials (one-off)
51
+ cat > agentbox.env <<'EOF'
52
+ E2B_API_KEY=agbx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
53
+ E2B_DOMAIN=agent-sandbox-data-plane.example.com/agent-sandbox/api/data
54
+ E2B_API_URL=https://agent-sandbox-data-plane.example.com/agent-sandbox/api/e2b
55
+ AGBX_CLUSTER_ID=cluster-a
56
+ AGBX_POOL_NAME=terminal-bench-pool
57
+ AGBX_IMAGE_PREFIX=registry.internal/agent-sandbox
58
+ EOF
59
+
60
+ # 2. Run Harbor (use the plugin via the official --environment-import-path flag)
61
+ harbor run \
62
+ -d terminal-bench@2.0 \
63
+ -a oracle \
64
+ --environment-import-path agent_sandbox_harbor:AgentSandboxEnvironment \
65
+ -n 16 -y \
66
+ --env-file agentbox.env
67
+ ```
68
+
69
+ ## Configuration
70
+
71
+ | Variable | Required | Description |
72
+ |----------|----------|-------------|
73
+ | `E2B_API_KEY` | yes | Agent Sandbox API key (`agbx_...`). |
74
+ | `AGBX_POOL_NAME` | yes | Pre-warmed pool name. |
75
+ | `E2B_DOMAIN` | no | Data-plane gateway, host[:port][/path]. Default is the in-cluster service. |
76
+ | `E2B_API_URL` | no | E2B-compatible control-plane URL, including scheme. |
77
+ | `AGBX_CLUSTER_ID` | no | Cluster id prefix (e.g. `cluster-a`). Omit for single-cluster setups. |
78
+ | `AGBX_IMAGE_PREFIX` | no | Mirror prefix (e.g. `registry.internal/agent-sandbox`). `docker.io/` is stripped before the prefix is applied. |
79
+ | `AGBX_HTTPS` | no | `true`/`false` for the data-plane scheme (default `true`). |
80
+ | `AGBX_STARTUP_TIMEOUT` | no | Sandbox startup timeout, seconds (default `300`). |
81
+ | `AGBX_READY_TIMEOUT` | no | Cold-image readiness ceiling, seconds (default `600`). |
82
+
83
+ ## How it works
84
+
85
+ `AgentSandboxEnvironment` subclasses Harbor's `E2BEnvironment` and overrides three methods:
86
+
87
+ - `_does_template_exist` → always returns `True`
88
+ - `_create_template` → no-op
89
+ - `_create_sandbox` → calls `AsyncSandbox.create(template="cluster::pool//image", secure=False, ...)`
90
+
91
+ `__init__` calls `super().__init__()` first, so Harbor's stock Dockerfile parsing still runs
92
+ (and sets `self._workdir` from the image's `WORKDIR`). The constructor then overrides
93
+ `self._template_name` with the Agent Sandbox pool shorthand.
94
+
95
+ At module import, `patch_e2b()` from
96
+ [`agent-sandbox-e2b`](https://pypi.org/project/agent-sandbox-e2b/) redirects the e2b SDK to
97
+ your Agent Sandbox endpoints.
98
+
99
+ See [INTEGRATION.md](INTEGRATION.md) for full design notes, the `--environment-import-path`
100
+ mechanism explanation, and operational guidance.
101
+
102
+ ## Compatibility
103
+
104
+ Each release build is tested against the latest published versions of
105
+ `harbor` and `e2b`. The pinned upper bound in `[project.optional-dependencies]` is updated
106
+ automatically by the release CI to reflect the highest verified `harbor` version.
107
+
108
+ ## License
109
+
110
+ Apache 2.0.
@@ -0,0 +1,92 @@
1
+ # agent-sandbox-harbor
2
+
3
+ A [Harbor](https://github.com/harbor-framework/harbor) environment plugin that runs Harbor
4
+ benchmarks (Terminal-Bench, SWE-bench, custom datasets) on
5
+ [Agent Sandbox](https://github.com/scitix/agent-sandbox) pre-warmed pools — no fork of Harbor
6
+ required.
7
+
8
+ Highlights:
9
+
10
+ - **Zero Harbor source changes.** Plugs into Harbor via the official
11
+ `--environment-import-path` extension point.
12
+ - **Skips Template Build.** Agent Sandbox uses a pre-warmed Pod pool with in-place image swap,
13
+ so the per-task Template Build step that E2B / Novita require is replaced by a single
14
+ `POST /v1/sandboxes` call.
15
+ - **Internal-mirror friendly.** A configurable image-prefix rewrites `docker.io/...` to your
16
+ private Distribution / Harbor registry.
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ pip install 'harbor[e2b]' agent-sandbox-harbor
22
+ ```
23
+
24
+ The plugin pulls [`agent-sandbox-e2b`](https://pypi.org/project/agent-sandbox-e2b/) as a hard
25
+ dependency (it calls `patch_e2b()` at import). `harbor` is an optional peer dependency, so the
26
+ package can be inspected / unit-tested without it; in real usage you install `harbor[e2b]`
27
+ yourself.
28
+
29
+ ## Quick start
30
+
31
+ ```bash
32
+ # 1. Set credentials (one-off)
33
+ cat > agentbox.env <<'EOF'
34
+ E2B_API_KEY=agbx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
35
+ E2B_DOMAIN=agent-sandbox-data-plane.example.com/agent-sandbox/api/data
36
+ E2B_API_URL=https://agent-sandbox-data-plane.example.com/agent-sandbox/api/e2b
37
+ AGBX_CLUSTER_ID=cluster-a
38
+ AGBX_POOL_NAME=terminal-bench-pool
39
+ AGBX_IMAGE_PREFIX=registry.internal/agent-sandbox
40
+ EOF
41
+
42
+ # 2. Run Harbor (use the plugin via the official --environment-import-path flag)
43
+ harbor run \
44
+ -d terminal-bench@2.0 \
45
+ -a oracle \
46
+ --environment-import-path agent_sandbox_harbor:AgentSandboxEnvironment \
47
+ -n 16 -y \
48
+ --env-file agentbox.env
49
+ ```
50
+
51
+ ## Configuration
52
+
53
+ | Variable | Required | Description |
54
+ |----------|----------|-------------|
55
+ | `E2B_API_KEY` | yes | Agent Sandbox API key (`agbx_...`). |
56
+ | `AGBX_POOL_NAME` | yes | Pre-warmed pool name. |
57
+ | `E2B_DOMAIN` | no | Data-plane gateway, host[:port][/path]. Default is the in-cluster service. |
58
+ | `E2B_API_URL` | no | E2B-compatible control-plane URL, including scheme. |
59
+ | `AGBX_CLUSTER_ID` | no | Cluster id prefix (e.g. `cluster-a`). Omit for single-cluster setups. |
60
+ | `AGBX_IMAGE_PREFIX` | no | Mirror prefix (e.g. `registry.internal/agent-sandbox`). `docker.io/` is stripped before the prefix is applied. |
61
+ | `AGBX_HTTPS` | no | `true`/`false` for the data-plane scheme (default `true`). |
62
+ | `AGBX_STARTUP_TIMEOUT` | no | Sandbox startup timeout, seconds (default `300`). |
63
+ | `AGBX_READY_TIMEOUT` | no | Cold-image readiness ceiling, seconds (default `600`). |
64
+
65
+ ## How it works
66
+
67
+ `AgentSandboxEnvironment` subclasses Harbor's `E2BEnvironment` and overrides three methods:
68
+
69
+ - `_does_template_exist` → always returns `True`
70
+ - `_create_template` → no-op
71
+ - `_create_sandbox` → calls `AsyncSandbox.create(template="cluster::pool//image", secure=False, ...)`
72
+
73
+ `__init__` calls `super().__init__()` first, so Harbor's stock Dockerfile parsing still runs
74
+ (and sets `self._workdir` from the image's `WORKDIR`). The constructor then overrides
75
+ `self._template_name` with the Agent Sandbox pool shorthand.
76
+
77
+ At module import, `patch_e2b()` from
78
+ [`agent-sandbox-e2b`](https://pypi.org/project/agent-sandbox-e2b/) redirects the e2b SDK to
79
+ your Agent Sandbox endpoints.
80
+
81
+ See [INTEGRATION.md](INTEGRATION.md) for full design notes, the `--environment-import-path`
82
+ mechanism explanation, and operational guidance.
83
+
84
+ ## Compatibility
85
+
86
+ Each release build is tested against the latest published versions of
87
+ `harbor` and `e2b`. The pinned upper bound in `[project.optional-dependencies]` is updated
88
+ automatically by the release CI to reflect the highest verified `harbor` version.
89
+
90
+ ## License
91
+
92
+ Apache 2.0.
@@ -0,0 +1,22 @@
1
+ # Copyright 2026 ScitiX
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """Agent Sandbox Harbor plugin — run Harbor benchmarks on Agent Sandbox pools."""
16
+
17
+ from .environment import AgentSandboxEnvironment
18
+
19
+ __version__ = "0.0.3"
20
+ SUPPORTED_HARBOR_MAX_VERSION = "0.7.1"
21
+
22
+ __all__ = ["SUPPORTED_HARBOR_MAX_VERSION", "AgentSandboxEnvironment"]
@@ -0,0 +1,172 @@
1
+ # Copyright 2026 ScitiX
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """
16
+ Agent Sandbox Harbor environment plugin.
17
+
18
+ Subclasses Harbor's stock ``E2BEnvironment`` so that:
19
+
20
+ * ``patch_e2b()`` runs at module import (before any AsyncSandbox call),
21
+ redirecting traffic to the Agent Sandbox E2B-compatible endpoint.
22
+ * The "template build" step is skipped (``alias_exists -> True``,
23
+ ``_create_template -> no-op``). Agent Sandbox uses a pre-warmed pool with
24
+ in-place image swap, so no template build is needed.
25
+ * The "template" string is rewritten to Agent Sandbox's pool+image shorthand
26
+ ``"<CLUSTER_ID>::<POOL_NAME>//<rewritten_image>"`` so that PostSandboxes on
27
+ the compat layer creates a sandbox from the pre-warmed pool.
28
+
29
+ Harbor's stock ``E2BEnvironment.__init__`` runs unchanged (we only subclass
30
+ and call ``super().__init__()``), so ``environment/Dockerfile`` is parsed for
31
+ ``WORKDIR`` and ``self._workdir`` is set automatically. Terminal-Bench 2.0
32
+ ships a Dockerfile for every task.
33
+
34
+ Required environment variables (typically via ``harbor run --env-file ...``):
35
+ E2B_API_KEY Agent Sandbox API key (``agbx_...``).
36
+ AGBX_POOL_NAME Pre-warmed pool name (e.g. ``terminal2``).
37
+
38
+ Optional environment variables:
39
+ E2B_DOMAIN Data-plane gateway host[:port][/path].
40
+ E2B_API_URL E2B-compatible control-plane URL (scheme://host).
41
+ AGBX_CLUSTER_ID Cluster id prefix (e.g. ``cetus``); omit for
42
+ single-cluster setups.
43
+ AGBX_IMAGE_PREFIX Internal mirror prefix
44
+ (e.g. ``registry.internal/agent-sandbox``).
45
+ ``docker.io/`` is stripped before the prefix is
46
+ applied.
47
+ AGBX_HTTPS ``true``/``false`` for the data-plane scheme
48
+ (default ``true``).
49
+ AGBX_STARTUP_TIMEOUT Sandbox startup timeout, seconds (default ``300``).
50
+ AGBX_READY_TIMEOUT Cold-image readiness ceiling, seconds
51
+ (default ``600``).
52
+ """
53
+
54
+ from __future__ import annotations
55
+
56
+ import asyncio
57
+ import os
58
+ import time
59
+
60
+ from agent_sandbox_e2b import patch_e2b
61
+
62
+ # CRITICAL: ``patch_e2b()`` must execute before ``AsyncSandbox.create`` is
63
+ # invoked. Doing it at module import means all later ``from e2b import ...``
64
+ # lines see the already-patched class methods. Harbor's lazy import of the e2b
65
+ # backend means this module is imported (and ``patch_e2b()`` runs) before
66
+ # Harbor's own ``harbor.environments.e2b`` module is loaded.
67
+ patch_e2b(
68
+ https=os.environ.get("AGBX_HTTPS", "true").lower() == "true",
69
+ domain=os.environ.get("E2B_DOMAIN") or None,
70
+ api_url=os.environ.get("E2B_API_URL") or None,
71
+ )
72
+
73
+ from e2b import AsyncSandbox # noqa: E402
74
+ from harbor.environments.e2b import E2BEnvironment # noqa: E402
75
+ from harbor.models.environment_type import EnvironmentType # noqa: E402
76
+
77
+
78
+ def _rewrite_image(raw_image: str) -> str:
79
+ """Strip ``docker.io/`` and apply the internal mirror prefix."""
80
+ if not raw_image:
81
+ return raw_image
82
+ if raw_image.startswith("docker.io/"):
83
+ raw_image = raw_image[len("docker.io/") :]
84
+ prefix = os.environ.get("AGBX_IMAGE_PREFIX", "").rstrip("/")
85
+ if prefix and not raw_image.startswith(prefix + "/"):
86
+ return f"{prefix}/{raw_image}"
87
+ return raw_image
88
+
89
+
90
+ class AgentSandboxEnvironment(E2BEnvironment):
91
+ """E2B-compatible Harbor environment that targets Agent Sandbox pools."""
92
+
93
+ @staticmethod
94
+ def type() -> EnvironmentType:
95
+ return EnvironmentType.E2B
96
+
97
+ @classmethod
98
+ def preflight(cls) -> None:
99
+ missing = [
100
+ v for v in ("E2B_API_KEY", "AGBX_POOL_NAME") if not os.environ.get(v)
101
+ ]
102
+ if missing:
103
+ raise SystemExit(
104
+ f"AgentSandboxEnvironment requires env vars: {', '.join(missing)}"
105
+ )
106
+
107
+ def __init__(self, *args, **kwargs):
108
+ # Let E2BEnvironment.__init__ parse environment/Dockerfile for WORKDIR
109
+ # and run its own validation. Terminal-Bench 2.0 ships a Dockerfile for
110
+ # every task, so the validation passes.
111
+ super().__init__(*args, **kwargs)
112
+
113
+ docker_image = self.task_env_config.docker_image
114
+ if not docker_image:
115
+ raise ValueError(
116
+ f"task '{self.environment_name}' has no environment.docker_image; "
117
+ "AgentSandboxEnvironment requires it to be set."
118
+ )
119
+
120
+ cluster = os.environ.get("AGBX_CLUSTER_ID", "").strip()
121
+ pool = os.environ["AGBX_POOL_NAME"]
122
+ image = _rewrite_image(docker_image)
123
+ prefix = f"{cluster}::" if cluster else ""
124
+ # PostSandboxes on the compat layer parses "<cluster>::<pool>//<image>".
125
+ # Replace the hash-based template name that the parent computed.
126
+ self._template_name = f"{prefix}{pool}//{image}"
127
+
128
+ # --- skip template build entirely ----------------------------------------
129
+
130
+ async def _does_template_exist(self) -> bool: # type: ignore[override]
131
+ return True
132
+
133
+ async def _create_template(self) -> None: # type: ignore[override]
134
+ return
135
+
136
+ # --- sandbox create: Agent Sandbox metadata + secure=False + ready poll ---
137
+
138
+ async def _create_sandbox(self) -> None: # type: ignore[override]
139
+ startup_timeout = os.environ.get("AGBX_STARTUP_TIMEOUT", "300")
140
+ metadata = {
141
+ "environment_name": self.environment_name,
142
+ "session_id": self.session_id,
143
+ "agentbox.scitix.ai/startup-timeout": startup_timeout,
144
+ }
145
+ self._sandbox = await AsyncSandbox.create(
146
+ self._template_name,
147
+ timeout=86_400,
148
+ secure=False,
149
+ metadata=metadata,
150
+ allow_internet_access=self.task_env_config.allow_internet,
151
+ )
152
+ # Cold-image pulls can leave ``AsyncSandbox.create`` returning before
153
+ # the envd daemon is reachable; the first ``commands.run()`` then fails
154
+ # with ``Code.unknown``. Block on a trivial exec until it succeeds.
155
+ ready_deadline = float(os.environ.get("AGBX_READY_TIMEOUT", "600"))
156
+ t0 = time.time()
157
+ last_err: Exception | None = None
158
+ while time.time() - t0 < ready_deadline:
159
+ try:
160
+ h = await self._sandbox.commands.run(
161
+ "true", background=True, timeout=0, user="root"
162
+ )
163
+ await h.wait()
164
+ return
165
+ except Exception as e: # noqa: BLE001
166
+ last_err = e
167
+ await asyncio.sleep(3)
168
+ raise TimeoutError(
169
+ f"Sandbox {self._sandbox.sandbox_id} not ready after "
170
+ f"{ready_deadline}s (template={self._template_name}); "
171
+ f"last error: {type(last_err).__name__}: {last_err}"
172
+ )
@@ -0,0 +1,110 @@
1
+ Metadata-Version: 2.4
2
+ Name: agent-sandbox-harbor
3
+ Version: 0.0.3
4
+ Summary: Agent Sandbox plugin for Harbor — run Terminal-Bench / SWE-bench / Harbor benchmarks on Agent Sandbox pools
5
+ License: Apache-2.0
6
+ Project-URL: Homepage, https://github.com/scitix/agent-sandbox
7
+ Project-URL: Source, https://github.com/scitix/agent-sandbox/tree/main/sdk/python/harbor
8
+ Requires-Python: >=3.12
9
+ Description-Content-Type: text/markdown
10
+ Requires-Dist: agent-sandbox-e2b>=0.0.2
11
+ Provides-Extra: harbor
12
+ Requires-Dist: harbor<=0.7.1,>=0.7.0; extra == "harbor"
13
+ Requires-Dist: e2b>=2.0.0; extra == "harbor"
14
+ Provides-Extra: dev
15
+ Requires-Dist: harbor>=0.7.0; extra == "dev"
16
+ Requires-Dist: e2b>=2.0.0; extra == "dev"
17
+ Requires-Dist: ruff>=0.4.0; extra == "dev"
18
+
19
+ # agent-sandbox-harbor
20
+
21
+ A [Harbor](https://github.com/harbor-framework/harbor) environment plugin that runs Harbor
22
+ benchmarks (Terminal-Bench, SWE-bench, custom datasets) on
23
+ [Agent Sandbox](https://github.com/scitix/agent-sandbox) pre-warmed pools — no fork of Harbor
24
+ required.
25
+
26
+ Highlights:
27
+
28
+ - **Zero Harbor source changes.** Plugs into Harbor via the official
29
+ `--environment-import-path` extension point.
30
+ - **Skips Template Build.** Agent Sandbox uses a pre-warmed Pod pool with in-place image swap,
31
+ so the per-task Template Build step that E2B / Novita require is replaced by a single
32
+ `POST /v1/sandboxes` call.
33
+ - **Internal-mirror friendly.** A configurable image-prefix rewrites `docker.io/...` to your
34
+ private Distribution / Harbor registry.
35
+
36
+ ## Installation
37
+
38
+ ```bash
39
+ pip install 'harbor[e2b]' agent-sandbox-harbor
40
+ ```
41
+
42
+ The plugin pulls [`agent-sandbox-e2b`](https://pypi.org/project/agent-sandbox-e2b/) as a hard
43
+ dependency (it calls `patch_e2b()` at import). `harbor` is an optional peer dependency, so the
44
+ package can be inspected / unit-tested without it; in real usage you install `harbor[e2b]`
45
+ yourself.
46
+
47
+ ## Quick start
48
+
49
+ ```bash
50
+ # 1. Set credentials (one-off)
51
+ cat > agentbox.env <<'EOF'
52
+ E2B_API_KEY=agbx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
53
+ E2B_DOMAIN=agent-sandbox-data-plane.example.com/agent-sandbox/api/data
54
+ E2B_API_URL=https://agent-sandbox-data-plane.example.com/agent-sandbox/api/e2b
55
+ AGBX_CLUSTER_ID=cluster-a
56
+ AGBX_POOL_NAME=terminal-bench-pool
57
+ AGBX_IMAGE_PREFIX=registry.internal/agent-sandbox
58
+ EOF
59
+
60
+ # 2. Run Harbor (use the plugin via the official --environment-import-path flag)
61
+ harbor run \
62
+ -d terminal-bench@2.0 \
63
+ -a oracle \
64
+ --environment-import-path agent_sandbox_harbor:AgentSandboxEnvironment \
65
+ -n 16 -y \
66
+ --env-file agentbox.env
67
+ ```
68
+
69
+ ## Configuration
70
+
71
+ | Variable | Required | Description |
72
+ |----------|----------|-------------|
73
+ | `E2B_API_KEY` | yes | Agent Sandbox API key (`agbx_...`). |
74
+ | `AGBX_POOL_NAME` | yes | Pre-warmed pool name. |
75
+ | `E2B_DOMAIN` | no | Data-plane gateway, host[:port][/path]. Default is the in-cluster service. |
76
+ | `E2B_API_URL` | no | E2B-compatible control-plane URL, including scheme. |
77
+ | `AGBX_CLUSTER_ID` | no | Cluster id prefix (e.g. `cluster-a`). Omit for single-cluster setups. |
78
+ | `AGBX_IMAGE_PREFIX` | no | Mirror prefix (e.g. `registry.internal/agent-sandbox`). `docker.io/` is stripped before the prefix is applied. |
79
+ | `AGBX_HTTPS` | no | `true`/`false` for the data-plane scheme (default `true`). |
80
+ | `AGBX_STARTUP_TIMEOUT` | no | Sandbox startup timeout, seconds (default `300`). |
81
+ | `AGBX_READY_TIMEOUT` | no | Cold-image readiness ceiling, seconds (default `600`). |
82
+
83
+ ## How it works
84
+
85
+ `AgentSandboxEnvironment` subclasses Harbor's `E2BEnvironment` and overrides three methods:
86
+
87
+ - `_does_template_exist` → always returns `True`
88
+ - `_create_template` → no-op
89
+ - `_create_sandbox` → calls `AsyncSandbox.create(template="cluster::pool//image", secure=False, ...)`
90
+
91
+ `__init__` calls `super().__init__()` first, so Harbor's stock Dockerfile parsing still runs
92
+ (and sets `self._workdir` from the image's `WORKDIR`). The constructor then overrides
93
+ `self._template_name` with the Agent Sandbox pool shorthand.
94
+
95
+ At module import, `patch_e2b()` from
96
+ [`agent-sandbox-e2b`](https://pypi.org/project/agent-sandbox-e2b/) redirects the e2b SDK to
97
+ your Agent Sandbox endpoints.
98
+
99
+ See [INTEGRATION.md](INTEGRATION.md) for full design notes, the `--environment-import-path`
100
+ mechanism explanation, and operational guidance.
101
+
102
+ ## Compatibility
103
+
104
+ Each release build is tested against the latest published versions of
105
+ `harbor` and `e2b`. The pinned upper bound in `[project.optional-dependencies]` is updated
106
+ automatically by the release CI to reflect the highest verified `harbor` version.
107
+
108
+ ## License
109
+
110
+ Apache 2.0.
@@ -0,0 +1,9 @@
1
+ README.md
2
+ pyproject.toml
3
+ agent_sandbox_harbor/__init__.py
4
+ agent_sandbox_harbor/environment.py
5
+ agent_sandbox_harbor.egg-info/PKG-INFO
6
+ agent_sandbox_harbor.egg-info/SOURCES.txt
7
+ agent_sandbox_harbor.egg-info/dependency_links.txt
8
+ agent_sandbox_harbor.egg-info/requires.txt
9
+ agent_sandbox_harbor.egg-info/top_level.txt
@@ -0,0 +1,10 @@
1
+ agent-sandbox-e2b>=0.0.2
2
+
3
+ [dev]
4
+ harbor>=0.7.0
5
+ e2b>=2.0.0
6
+ ruff>=0.4.0
7
+
8
+ [harbor]
9
+ harbor<=0.7.1,>=0.7.0
10
+ e2b>=2.0.0
@@ -0,0 +1 @@
1
+ agent_sandbox_harbor
@@ -0,0 +1,39 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "agent-sandbox-harbor"
7
+ dynamic = ["version"]
8
+ description = "Agent Sandbox plugin for Harbor — run Terminal-Bench / SWE-bench / Harbor benchmarks on Agent Sandbox pools"
9
+ readme = "README.md"
10
+ license = { text = "Apache-2.0" }
11
+ requires-python = ">=3.12"
12
+ dependencies = [
13
+ "agent-sandbox-e2b>=0.0.2",
14
+ ]
15
+ # harbor is an optional peer dependency installed by users via `harbor[e2b]`;
16
+ # we don't pin it as a hard dependency to avoid version conflicts with users
17
+ # who pin a specific harbor version themselves.
18
+
19
+ [project.optional-dependencies]
20
+ harbor = ["harbor>=0.7.0,<=0.7.1", "e2b>=2.0.0"]
21
+ dev = ["harbor>=0.7.0", "e2b>=2.0.0", "ruff>=0.4.0"]
22
+
23
+ [tool.setuptools.dynamic]
24
+ version = { attr = "agent_sandbox_harbor.__version__" }
25
+
26
+ [tool.setuptools.packages.find]
27
+ where = ["."]
28
+ include = ["agent_sandbox_harbor*"]
29
+
30
+ [project.urls]
31
+ Homepage = "https://github.com/scitix/agent-sandbox"
32
+ Source = "https://github.com/scitix/agent-sandbox/tree/main/sdk/python/harbor"
33
+
34
+ [tool.ruff]
35
+ line-length = 100
36
+ target-version = "py312"
37
+
38
+ [tool.ruff.lint]
39
+ select = ["E", "F", "I", "UP"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+