withruntime 0.7.0__tar.gz → 0.7.1__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.
- {withruntime-0.7.0/withruntime.egg-info → withruntime-0.7.1}/PKG-INFO +6 -1
- {withruntime-0.7.0 → withruntime-0.7.1}/pyproject.toml +8 -1
- {withruntime-0.7.0 → withruntime-0.7.1}/tests/test_e2b_sandbox.py +23 -0
- withruntime-0.7.1/withruntime/_version.py +1 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/e2b/_async_sandbox.py +6 -2
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/e2b/_core.py +16 -5
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/e2b/_sync_sandbox.py +6 -2
- {withruntime-0.7.0 → withruntime-0.7.1/withruntime.egg-info}/PKG-INFO +6 -1
- withruntime-0.7.0/withruntime/_version.py +0 -1
- {withruntime-0.7.0 → withruntime-0.7.1}/LICENSE +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/README.md +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/setup.cfg +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/tests/test_account_errors.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/tests/test_async_stream_cleanup.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/tests/test_audit.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/tests/test_billing.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/tests/test_capacity_wait.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/tests/test_client.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/tests/test_daytona.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/tests/test_deepagents.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/tests/test_e2b_code_interpreter.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/tests/test_eval_sandbox.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/tests/test_exec_stream.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/tests/test_files_download.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/tests/test_files_mode.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/tests/test_harbor.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/tests/test_identity_token.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/tests/test_images_v2.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/tests/test_images_volumes_interpreter.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/tests/test_inspect_ai.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/tests/test_late_answer.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/tests/test_lifecycle_settings.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/tests/test_limits.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/tests/test_mounts.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/tests/test_network_funding.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/tests/test_network_products.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/tests/test_observability.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/tests/test_openai_agents.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/tests/test_previews_network_desktop.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/tests/test_proxy.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/tests/test_referrals.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/tests/test_secrets.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/tests/test_snapshot_after_fork.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/tests/test_sso.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/tests/test_switching.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/tests/test_tools.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/tests/test_vercel.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/tests/test_volume_backups.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/tests/test_wake_awake.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/tests/test_wallet.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/tests/test_watch.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/__init__.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_async_client.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_async_products/__init__.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_async_products/audit.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_async_products/billing.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_async_products/desktop.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_async_products/images.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_async_products/interpreter.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_async_products/limits.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_async_products/mcp.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_async_products/mounts.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_async_products/network.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_async_products/network_products.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_async_products/observability.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_async_products/previews.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_async_products/referrals.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_async_products/secrets.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_async_products/sso.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_async_products/switching.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_async_products/volumes.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_async_products/watch.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_clock.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_connection.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_errors.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_eval_sandbox.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_http.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_proxy.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_sync_client.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_sync_products/__init__.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_sync_products/audit.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_sync_products/billing.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_sync_products/desktop.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_sync_products/images.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_sync_products/interpreter.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_sync_products/limits.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_sync_products/mcp.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_sync_products/mounts.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_sync_products/network.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_sync_products/network_products.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_sync_products/observability.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_sync_products/previews.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_sync_products/referrals.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_sync_products/secrets.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_sync_products/sso.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_sync_products/switching.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_sync_products/volumes.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_sync_products/watch.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_tunnel.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/_ws.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/daytona/__init__.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/daytona/_async_daytona.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/daytona/_async_io.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/daytona/_core.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/daytona/_sync_daytona.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/daytona/_sync_io.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/deepagents.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/e2b/__init__.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/e2b/_async_io.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/e2b/_sync_io.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/e2b/code_interpreter/__init__.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/e2b/code_interpreter/_async_ci.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/e2b/code_interpreter/_models.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/e2b/code_interpreter/_sync_ci.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/harbor.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/inspect_ai.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/openai_agents.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/tools.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/vercel/__init__.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/vercel/_async_io.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/vercel/_async_sandbox.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/vercel/_core.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/vercel/_sync_io.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/vercel/_sync_sandbox.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/vercel/api.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/vercel/sandbox/__init__.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/vercel/sandbox/sync.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/wallet.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime/webhooks.py +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime.egg-info/SOURCES.txt +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime.egg-info/dependency_links.txt +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime.egg-info/entry_points.txt +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime.egg-info/requires.txt +0 -0
- {withruntime-0.7.0 → withruntime-0.7.1}/withruntime.egg-info/top_level.txt +0 -0
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: withruntime
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.1
|
|
4
4
|
Summary: Runtime Cloud: one client (sync and async) for every Runtime product. Sandboxes first.
|
|
5
5
|
License: Apache-2.0
|
|
6
|
+
Project-URL: Homepage, https://withruntime.com
|
|
7
|
+
Project-URL: Documentation, https://withruntime.com/docs/python
|
|
8
|
+
Project-URL: Source, https://github.com/withruntime/runtime/tree/main/sdks/python
|
|
9
|
+
Project-URL: Issues, https://github.com/withruntime/runtime/issues
|
|
10
|
+
Keywords: sandbox,ai-agents,agents,microvm,firecracker,code-execution,code-interpreter,mcp,llm
|
|
6
11
|
Requires-Python: >=3.10
|
|
7
12
|
Description-Content-Type: text/markdown
|
|
8
13
|
License-File: LICENSE
|
|
@@ -4,12 +4,19 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "withruntime"
|
|
7
|
-
version = "0.7.
|
|
7
|
+
version = "0.7.1"
|
|
8
8
|
description = "Runtime Cloud: one client (sync and async) for every Runtime product. Sandboxes first."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { text = "Apache-2.0" }
|
|
11
11
|
requires-python = ">=3.10"
|
|
12
12
|
dependencies = []
|
|
13
|
+
keywords = ["sandbox", "ai-agents", "agents", "microvm", "firecracker", "code-execution", "code-interpreter", "mcp", "llm"]
|
|
14
|
+
|
|
15
|
+
[project.urls]
|
|
16
|
+
Homepage = "https://withruntime.com"
|
|
17
|
+
Documentation = "https://withruntime.com/docs/python"
|
|
18
|
+
Source = "https://github.com/withruntime/runtime/tree/main/sdks/python"
|
|
19
|
+
Issues = "https://github.com/withruntime/runtime/issues"
|
|
13
20
|
|
|
14
21
|
[project.optional-dependencies]
|
|
15
22
|
# withruntime.openai_agents: a sandbox client for the OpenAI Agents SDK's SandboxAgent.
|
|
@@ -145,6 +145,29 @@ class Commands(Base):
|
|
|
145
145
|
result = sbx.commands.run("python3 -c 'print(\"x\"*70000)'", timeout=60)
|
|
146
146
|
self.assertEqual((result.exit_code, len(result.stdout), len(result.stderr)), (0, 70_001, 70_000))
|
|
147
147
|
|
|
148
|
+
def test_output_dropped_before_it_was_read_is_marked_and_warned(self):
|
|
149
|
+
# A customer's report, 24 September 2026: output lost in a stream came
|
|
150
|
+
# back looking whole.
|
|
151
|
+
sbx = self.create()
|
|
152
|
+
with warnings.catch_warnings(record=True) as caught:
|
|
153
|
+
warnings.simplefilter("always")
|
|
154
|
+
self.world.exec = lambda *_: Result(0, "tail\n", lost=True)
|
|
155
|
+
self.assertTrue(sbx.commands.run("big").truncated)
|
|
156
|
+
self.world.exec = lambda *_: Result(1, "tail\n", lost=True)
|
|
157
|
+
with self.assertRaises(CommandExitException) as failed:
|
|
158
|
+
sbx.commands.run("big")
|
|
159
|
+
self.assertTrue(failed.exception.truncated)
|
|
160
|
+
self.world.exec = lambda *_: Result(0, "whole\n")
|
|
161
|
+
self.assertFalse(sbx.commands.run("small").truncated)
|
|
162
|
+
self.assertEqual(len(caught), 2)
|
|
163
|
+
self.assertIn("output was dropped", str(caught[0].message))
|
|
164
|
+
self.world.output = lambda _: [{"type": "truncated", "droppedBytes": 10, "resumeAt": 10},
|
|
165
|
+
{"type": "stdout", "data": "tail\n", "offset": 10},
|
|
166
|
+
{"type": "exit", "exitCode": 0, "state": "exited", "timedOut": False}]
|
|
167
|
+
with warnings.catch_warnings():
|
|
168
|
+
warnings.simplefilter("ignore")
|
|
169
|
+
self.assertTrue(sbx.commands.run("big", background=True).wait().truncated)
|
|
170
|
+
|
|
148
171
|
def test_non_zero_exit(self):
|
|
149
172
|
self.world.exec = lambda *_: Result(3, "partial\n", "boom\n")
|
|
150
173
|
sbx = self.create()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
VERSION = "0.7.1"
|
|
@@ -51,6 +51,7 @@ class AsyncCommandHandle:
|
|
|
51
51
|
self._stdout = ""
|
|
52
52
|
self._stderr = ""
|
|
53
53
|
self._exit: Optional[Dict[str, Any]] = None
|
|
54
|
+
self._truncated = False
|
|
54
55
|
self._failure: Optional[BaseException] = None
|
|
55
56
|
self._disconnected = False
|
|
56
57
|
self._task = start(self._follow)
|
|
@@ -66,6 +67,8 @@ class AsyncCommandHandle:
|
|
|
66
67
|
elif event["type"] == "stderr":
|
|
67
68
|
self._stderr += event["data"]
|
|
68
69
|
await call(self._on_stderr, event["data"])
|
|
70
|
+
elif event["type"] == "truncated":
|
|
71
|
+
self._truncated = True
|
|
69
72
|
elif event["type"] == "exit":
|
|
70
73
|
self._exit = event
|
|
71
74
|
except Exception as error: # noqa: BLE001
|
|
@@ -110,7 +113,7 @@ class AsyncCommandHandle:
|
|
|
110
113
|
"commands.connect(pid)." if self._disconnected
|
|
111
114
|
else "The command's output ended without an exit.")
|
|
112
115
|
return core.settle(self._exit.get("exitCode"), self._stdout, self._stderr,
|
|
113
|
-
bool(self._exit.get("timedOut")), self._timeout_ms)
|
|
116
|
+
bool(self._exit.get("timedOut")), self._timeout_ms, self._truncated)
|
|
114
117
|
|
|
115
118
|
async def disconnect(self) -> None:
|
|
116
119
|
"""Stops receiving output; the command keeps running."""
|
|
@@ -162,7 +165,8 @@ class AsyncCommands:
|
|
|
162
165
|
result = await _guard("sandbox", lambda: self._sandbox.runtime.exec(
|
|
163
166
|
cmd, cwd=cwd, env=self._env(envs), timeout_ms=timeout_ms,
|
|
164
167
|
on_stdout=wrap(on_stdout) or core.whole_output, on_stderr=wrap(on_stderr)))
|
|
165
|
-
return core.settle(result.exit_code, result.stdout, result.stderr, result.timed_out, timeout_ms
|
|
168
|
+
return core.settle(result.exit_code, result.stdout, result.stderr, result.timed_out, timeout_ms,
|
|
169
|
+
result.stdout_truncated or result.stderr_truncated)
|
|
166
170
|
|
|
167
171
|
async def _start(self, cmd: str, envs: Optional[Dict[str, str]], cwd: Optional[str], stdin: bool,
|
|
168
172
|
timeout_ms: int, on_stdout: Any, on_stderr: Any) -> AsyncCommandHandle:
|
|
@@ -92,6 +92,10 @@ class CommandResult:
|
|
|
92
92
|
stdout: str
|
|
93
93
|
exit_code: int
|
|
94
94
|
error: Optional[str]
|
|
95
|
+
#: Runtime's addition: some of the command's output was dropped before it
|
|
96
|
+
#: was read, so ``stdout`` and ``stderr`` are missing part of it. A warning
|
|
97
|
+
#: says so too.
|
|
98
|
+
truncated: bool = False
|
|
95
99
|
|
|
96
100
|
|
|
97
101
|
@dataclass
|
|
@@ -323,21 +327,28 @@ def command_timeout_ms(timeout: Optional[float]) -> int:
|
|
|
323
327
|
return min(int(math.ceil(timeout * 1000)), LONGEST_MS)
|
|
324
328
|
|
|
325
329
|
|
|
326
|
-
def to_result(exit_code: Optional[int], stdout: str, stderr: str) -> CommandResult:
|
|
330
|
+
def to_result(exit_code: Optional[int], stdout: str, stderr: str, truncated: bool = False) -> CommandResult:
|
|
327
331
|
code = -1 if exit_code is None else exit_code
|
|
328
332
|
error = None if code == 0 else ("terminated by a signal" if exit_code is None else f"exit status {code}")
|
|
329
|
-
return CommandResult(stderr=stderr, stdout=stdout, exit_code=code, error=error)
|
|
333
|
+
return CommandResult(stderr=stderr, stdout=stdout, exit_code=code, error=error, truncated=truncated)
|
|
330
334
|
|
|
331
335
|
|
|
332
|
-
def settle(exit_code: Optional[int], stdout: str, stderr: str, timed_out: bool, timeout_ms: int
|
|
336
|
+
def settle(exit_code: Optional[int], stdout: str, stderr: str, timed_out: bool, timeout_ms: int,
|
|
337
|
+
truncated: bool = False) -> CommandResult:
|
|
338
|
+
"""E2B never loses output, so a result that did says so in ``truncated``
|
|
339
|
+
rather than passing as whole."""
|
|
333
340
|
if timed_out:
|
|
334
341
|
raise TimeoutException(
|
|
335
342
|
f"Command timed out after {timeout_ms} ms: this error is likely due to exceeding 'timeout'. "
|
|
336
343
|
"Pass a larger 'timeout', or 0 for no limit.")
|
|
337
|
-
result = to_result(exit_code, stdout, stderr)
|
|
344
|
+
result = to_result(exit_code, stdout, stderr, truncated)
|
|
345
|
+
if truncated:
|
|
346
|
+
warnings.warn("Part of the command's output was dropped before it was read, so stdout and stderr are "
|
|
347
|
+
"incomplete (result.truncated). Write large output to a file and read it with "
|
|
348
|
+
"sandbox.files.read.", stacklevel=3)
|
|
338
349
|
if result.exit_code != 0:
|
|
339
350
|
raise CommandExitException(stderr=result.stderr, stdout=result.stdout, exit_code=result.exit_code,
|
|
340
|
-
error=result.error)
|
|
351
|
+
error=result.error, truncated=result.truncated)
|
|
341
352
|
return result
|
|
342
353
|
|
|
343
354
|
|
|
@@ -50,6 +50,7 @@ class CommandHandle:
|
|
|
50
50
|
self._stdout = ""
|
|
51
51
|
self._stderr = ""
|
|
52
52
|
self._exit: Optional[Dict[str, Any]] = None
|
|
53
|
+
self._truncated = False
|
|
53
54
|
self._failure: Optional[BaseException] = None
|
|
54
55
|
self._disconnected = False
|
|
55
56
|
self._task = start(self._follow)
|
|
@@ -65,6 +66,8 @@ class CommandHandle:
|
|
|
65
66
|
elif event["type"] == "stderr":
|
|
66
67
|
self._stderr += event["data"]
|
|
67
68
|
call(self._on_stderr, event["data"])
|
|
69
|
+
elif event["type"] == "truncated":
|
|
70
|
+
self._truncated = True
|
|
68
71
|
elif event["type"] == "exit":
|
|
69
72
|
self._exit = event
|
|
70
73
|
except Exception as error: # noqa: BLE001
|
|
@@ -109,7 +112,7 @@ class CommandHandle:
|
|
|
109
112
|
"commands.connect(pid)." if self._disconnected
|
|
110
113
|
else "The command's output ended without an exit.")
|
|
111
114
|
return core.settle(self._exit.get("exitCode"), self._stdout, self._stderr,
|
|
112
|
-
bool(self._exit.get("timedOut")), self._timeout_ms)
|
|
115
|
+
bool(self._exit.get("timedOut")), self._timeout_ms, self._truncated)
|
|
113
116
|
|
|
114
117
|
def disconnect(self) -> None:
|
|
115
118
|
"""Stops receiving output; the command keeps running."""
|
|
@@ -161,7 +164,8 @@ class Commands:
|
|
|
161
164
|
result = _guard("sandbox", lambda: self._sandbox.runtime.exec(
|
|
162
165
|
cmd, cwd=cwd, env=self._env(envs), timeout_ms=timeout_ms,
|
|
163
166
|
on_stdout=wrap(on_stdout) or core.whole_output, on_stderr=wrap(on_stderr)))
|
|
164
|
-
return core.settle(result.exit_code, result.stdout, result.stderr, result.timed_out, timeout_ms
|
|
167
|
+
return core.settle(result.exit_code, result.stdout, result.stderr, result.timed_out, timeout_ms,
|
|
168
|
+
result.stdout_truncated or result.stderr_truncated)
|
|
165
169
|
|
|
166
170
|
def _start(self, cmd: str, envs: Optional[Dict[str, str]], cwd: Optional[str], stdin: bool,
|
|
167
171
|
timeout_ms: int, on_stdout: Any, on_stderr: Any) -> CommandHandle:
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: withruntime
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.1
|
|
4
4
|
Summary: Runtime Cloud: one client (sync and async) for every Runtime product. Sandboxes first.
|
|
5
5
|
License: Apache-2.0
|
|
6
|
+
Project-URL: Homepage, https://withruntime.com
|
|
7
|
+
Project-URL: Documentation, https://withruntime.com/docs/python
|
|
8
|
+
Project-URL: Source, https://github.com/withruntime/runtime/tree/main/sdks/python
|
|
9
|
+
Project-URL: Issues, https://github.com/withruntime/runtime/issues
|
|
10
|
+
Keywords: sandbox,ai-agents,agents,microvm,firecracker,code-execution,code-interpreter,mcp,llm
|
|
6
11
|
Requires-Python: >=3.10
|
|
7
12
|
Description-Content-Type: text/markdown
|
|
8
13
|
License-File: LICENSE
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
VERSION = "0.7.0"
|
|
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
|
|
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
|
|
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
|
|
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
|