Skip to content

Conversation

@luke-lombardi
Copy link
Contributor

@luke-lombardi luke-lombardi commented Jan 11, 2026

Summary by cubic

Add an async API for the sandbox via .aio interfaces, enabling non-blocking process, filesystem, Docker, and lifecycle operations with async streaming of stdout/stderr/logs. Adds retries for transient connection errors and caches stdout/stderr/log streams for consistent reads, while maintaining full backward compatibility with the sync API.

  • New Features

    • .aio properties for SandboxInstance, ProcessManager, Process, FileSystem, and DockerManager.
    • Async classes: AsyncSandboxInstance/Process/ProcessManager/FileSystem/DockerManager/DockerResult/DockerComposeStack, plus async stdout/stderr/log streams.
    • Async methods mirror the sync API (run_code, exec, list_processes, upload/download, expose_port, update_ttl, update_network_permissions, list_urls, Docker run/build/pull/push/compose).
    • Uses asyncio.to_thread under the hood; no backend changes required.
  • Refactors

    • Added retry_on_transient_error for exec/status/stream reads to handle transient gRPC/connection errors.
    • Cache stdout/stderr/logs streams to preserve buffer state across accesses.
    • Exclude _aio and cached stream attributes from getstate to keep objects picklable; minor import/order cleanups.

Written for commit 75db4cc. Summary will update on new commits.

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 1 file

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="sdk/src/beta9/abstractions/sandbox.py">

<violation number="1" location="sdk/src/beta9/abstractions/sandbox.py:3430">
P2: The `logs()` async generator buffers all output before yielding, defeating the streaming purpose. It waits for `list(self._sync.logs())` to complete (collecting ALL logs) before yielding any lines. For long-running operations like Docker builds, users won't see any output until the entire operation completes.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

@luke-lombardi luke-lombardi merged commit 86dd8ac into main Jan 11, 2026
4 checks passed
@luke-lombardi luke-lombardi deleted the ll/async-sandbox branch January 11, 2026 21:29
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 3 files (changes from recent commits).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="sdk/src/beta9/utils.py">

<violation number="1" location="sdk/src/beta9/utils.py:40">
P3: The comment says "Exponential backoff" but the formula `delay * (attempt + 1)` produces linear backoff. Either update the comment to "linear backoff" or change the formula to `delay * (2 ** attempt)` for true exponential backoff.</violation>

<violation number="2" location="sdk/src/beta9/utils.py:44">
P2: If `max_retries=0` is passed, the loop never executes and `raise last_exception` will raise `None`, causing a `TypeError`. Consider adding a guard or raising a more descriptive error.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

continue
# Non-transient error, raise immediately
raise
raise last_exception
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Jan 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: If max_retries=0 is passed, the loop never executes and raise last_exception will raise None, causing a TypeError. Consider adding a guard or raising a more descriptive error.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At sdk/src/beta9/utils.py, line 44:

<comment>If `max_retries=0` is passed, the loop never executes and `raise last_exception` will raise `None`, causing a `TypeError`. Consider adding a guard or raising a more descriptive error.</comment>

<file context>
@@ -2,11 +2,48 @@
+                    continue
+            # Non-transient error, raise immediately
+            raise
+    raise last_exception
+
+
</file context>
Suggested change
raise last_exception
if last_exception is None:
raise ValueError("max_retries must be at least 1")
raise last_exception
Fix with Cubic

):
last_exception = e
if attempt < max_retries - 1:
time.sleep(delay * (attempt + 1)) # Exponential backoff
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Jan 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: The comment says "Exponential backoff" but the formula delay * (attempt + 1) produces linear backoff. Either update the comment to "linear backoff" or change the formula to delay * (2 ** attempt) for true exponential backoff.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At sdk/src/beta9/utils.py, line 40:

<comment>The comment says "Exponential backoff" but the formula `delay * (attempt + 1)` produces linear backoff. Either update the comment to "linear backoff" or change the formula to `delay * (2 ** attempt)` for true exponential backoff.</comment>

<file context>
@@ -2,11 +2,48 @@
+            ):
+                last_exception = e
+                if attempt < max_retries - 1:
+                    time.sleep(delay * (attempt + 1))  # Exponential backoff
+                    continue
+            # Non-transient error, raise immediately
</file context>
Suggested change
time.sleep(delay * (attempt + 1)) # Exponential backoff
time.sleep(delay * (2 ** attempt)) # Exponential backoff
Fix with Cubic

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants