feat: onResume option on connect/resume - #1800
Conversation
Picks up `memory` on ConnectSandbox and ResumedSandbox, which the API serves and the spec no longer marks unimplemented. The rest is churn the pin had fallen behind: the removed access-token models, httpsPorts and the reworded transform rules on the network config, and Rig schemas that survive the tag filter as orphan components. Signed-off-by: Babis Chalios <babis.chalios@e2b.dev>
Resuming a memory-inclusive snapshot whose memory image wedges the guest had no self-serve way out. `onResume: 'reboot'` (`on_resume` in Python) cold-boots from disk state instead, and the memory snapshot is never touched, so a later restore still works. 'restore' is the API's own default and travels as an absent `memory` field; only the 'reboot' literal sends `memory: false`, so an unrecognized value from an untyped caller falls back to a memory restore rather than silently cold-booting. Signed-off-by: Babis Chalios <babis.chalios@e2b.dev>
PR SummaryMedium Risk Overview The option is keyword-only in Python, works on static and instance OpenAPI / generated client churn from the updated spec pin: optional Reviewed by Cursor Bugbot for commit 39424d6. Bugbot is set up for automated code reviews on this repo. Configure here. |
🦋 Changeset detectedLatest commit: 39424d6 The changes in this PR will be included in the next version bump. This PR includes changesets to release 2 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Package ArtifactsBuilt from aa6714c. Download artifacts from this workflow run. JS SDK ( npm install ./e2b-2.46.2-feat-on-resume-option.0.tgzCLI ( npm install ./e2b-cli-2.18.1-feat-on-resume-option.0.tgzCode Interpreter JS SDK ( npm install ./e2b-code-interpreter-2.7.3-feat-on-resume-option.0.tgzDesktop JS SDK ( npm install ./e2b-desktop-2.3.5-feat-on-resume-option.0.tgzPython SDK ( pip install ./e2b-2.46.4+feat.on.resume.option-py3-none-any.whlCode Interpreter Python SDK ( pip install ./e2b_code_interpreter-2.9.3+feat.on.resume.option-py3-none-any.whlDesktop Python SDK ( pip install ./e2b_desktop-2.4.6+feat.on.resume.option-py3-none-any.whl |
There was a problem hiding this comment.
TASTE.md review
Checked the SDK-facing changes (packages/js-sdk/src/sandbox/sandboxApi.ts, index.ts, packages/python-sdk/e2b/sandbox/sandbox_api.py, sandbox_sync/, sandbox_async/, __init__.py, and the new tests) against: parity (T-1, T-2, T-10), API shape (T-3, T-6, T-14, T-15, T-19, T-22, T-23), boundary mapping (T-18), entry-point exports (T-54), client-side validation (T-52), and docs (T-69–T-74). Generated files (schema.gen.ts, api/client/models/*, spec/) were not judged.
Violations: 1 (low severity, same issue mirrored in sync/async Python — flagged inline on both).
- T-3 / T-1d —
on_resumelands as another positional-with-default in the Pythonconnect()signatures, extending the existingtimeoutinto a chain of optional positionals (Sandbox.connect(id, 300, "reboot")now type-checks). Since JS carries it inSandboxConnectOpts, the Python mirror should be keyword-only.timeout/loggerare pre-existing and out of scope, so a*separator can't be dropped in without moving them; noted as a design-debt item rather than something to block on.
Everything else lines up well: 'restore' | 'reboot' instead of a memory: boolean mirror of the wire field (T-14); the wire boolean is mapped at the boundary and the generated ConnectSandbox type never reaches users (T-18); SandboxOnResume is a named, exported type (export type in JS, __all__ in Python — T-23, T-54); no client-side check of whether the deployment supports filesystem-only resume (T-52); all four Python connect docstrings plus the JS option JSDoc document the parameter, default, and rejection behavior (T-69, T-74). Observation, not a violation: onResume/on_resume reuses the on<Event> shape T-27 reserves for callbacks, but onTimeout already set that precedent for lifecycle action config, so consistency wins here.
Landing it after `timeout` made `Sandbox.connect(id, 300, "reboot")` a valid call, while JS only accepts the option through SandboxConnectOpts. Placing it after `logger` behind a `*` separator keeps both pre-existing parameters positional, so nothing existing moves. Signed-off-by: Babis Chalios <babis.chalios@e2b.dev>
The gate short-circuits a memoryless snapshot before it consults the feature flag, and a running sandbox never reaches the gate, so "not enabled rejects reboot" was only true for a paused snapshot that holds memory. Signed-off-by: Babis Chalios <babis.chalios@e2b.dev>
Resuming a paused sandbox always restores its memory snapshot, so a snapshot whose memory image wedges the guest has no self-serve way out.
onResume: 'reboot'cold-boots from the sandbox's disk state instead and leaves the memory snapshot untouched, so a later'restore'still works.'restore'remains the default and keeps travelling as an omittedmemoryfield — only the'reboot'literal sendsmemory: false, so an unrecognized value from an untyped caller falls back to a memory restore rather than silently cold-booting.Disk state carries crash-recovery semantics, so writes not flushed before the pause may be lost. Where filesystem-only resume is not enabled, a
'reboot'that would actually drop memory is rejected with an error rather than quietly restoring it. The no-op cases (a snapshot holding no memory, a sandbox still running) never reach that gate and succeed either way — the API short-circuits them before it consults the flag.Draft until the spec pin is real. These fields are still marked
x-not-implemented: trueupstream, andredocly.yaml'sfilter-outprunes the marked property, so codegen at any current pin produces clients with nomemoryfield at all. Pending the infra commit that drops the marker,spec/openapi.ymlhere is hand-placed at its expected post-sync content andspec/infra-refis a placeholder — the Generated files check is expected red. Before this leaves draft the pin gets repointed at the real commit andmake codegenre-run, so the tracked spec comes from Copybara and is byte-identical to upstream.The rest of the spec diff is churn the pin had fallen behind by: removed access-token models,
httpsPortsand reworded transform rules on the network config,Rig*schemas that survive the tag filter as orphan components, and the resume request body becoming optional.Verified: 5 JS + 10 Python request-shape tests over sync, async, instance and static-by-id forms, each assertion mutation-checked (flip the literal to
!== 'restore', forcefalse, drop the guard, drop each forwarding hop — every mutant reddens exactly the intended row).pnpm run lint,formatandtypecheckclean. The credential-backed suites can't run without anE2B_API_KEY: locally they fail identically tomain(231 JS, 426 Python, byte-identical failure sets), so CI's run is the real check there.