* feat(e2b-sandbox): make mount upload deadline configurable
Replace the hardcoded 120-second mount upload deadline with a
configurable `mount_upload_deadline_seconds` key read from
SandboxConfig (extra=allow). The value is validated: zero and
negative inputs are clamped to 1 second. Omitting the key
preserves the existing 120-second default.
This addresses the follow-up from PR #4842 review: operators
with large mounts or slow networks can now size the deadline to
their deployment without changing code.
* fix(e2b-sandbox): address review feedback on configurable deadline
- Remove import-time default capture from _mount_deadline_reason()
and _MountUploadBudget.deadline_seconds to prevent silent drift.
- Add warning log when mount_upload_deadline_seconds is clamped to 1
(was silent before).
- Update AGENTS.md E2B Mount Uploads section: deadline is now
configurable, not fixed 120.
- Add mount_upload_deadline_seconds to YAML examples in provider
docstring and __init__.py.
- Add config-path test that exercises SandboxConfig -> _load_config ->
_apply_mounts end-to-end.
* feat(e2b-sandbox): surface structured mount upload result on sandbox
Introduce MountUploadResult dataclass and attach it to
E2BSandbox.mount_upload_result after creation. This makes mount
truncation observable in code without re-parsing Gateway logs.
_apply_mounts() now returns MountUploadResult with truncated, reason,
and upload totals. _create_sandbox() captures the result, stores it on
the sandbox instance, and records it in a provider-level map so the
result survives warm-pool reclaim and reconnect.
MountUploadResult.truncated is True only when the upload pass was
stopped early by a resource limit (deadline, file count cap, or byte
budget). Individual mount failures (missing host path, SDK errors) are
logged but do NOT set truncated.
Tests cover: success totals, deadline truncation, file-count truncation,
byte-budget truncation, non-limit failure not reported as truncation,
missing host path not reported as truncation, create→sandbox wiring,
and create→release→warm-pool→acquire result preservation.
* fix(e2b-sandbox-provider): fix _mount_results lifecycle leak and review findings
- Add _forget_mount_result() helper and call it at all terminal sandbox
paths: _reuse_in_process_sandbox dead-evict, _reclaim_warm_pool_sandbox
reconnect/dead/bootstrap/ownership/shutdown failure branches,
_forget_local_sandbox, _kill_and_close. Prevents unbounded dict growth
over a long-running Gateway process.
- Make MountUploadResult @dataclass(frozen=True) to prevent silent mutation
of the shared reference between provider map and sandbox attribute.
- Move _mount_results insert under self._lock in _create_sandbox to match
the read discipline in _register_connected_sandbox.
- Guard _resolve_mount_upload_deadline against None (YAML explicit null)
to avoid int(None) TypeError.
- Add 5 regression tests covering each bypass path and the frozen invariant.
* fix(e2b-sandbox-provider): add _forget_mount_result to _evict_oldest_warm branches
Add _forget_mount_result() calls to all four terminal exit paths in the
E2B _evict_oldest_warm override (reconnect failure, already-gone, kill
failure, kill success). The peer-owned path already cleans up via
_forget_local_sandbox. Add test_evict_oldest_warm_cleans_mount_result to
pin the kill-success branch.
* docs: reduce agent guidance size
---------
Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
* fix(memory): cancel buffered extraction when agent is deleted or cleared
* fix(memory): cancel buffered work before agent delete
Address review: cancel before/after delete to close the rmtree race,
scope user_id=None cancels to the legacy root only, and import memory
helpers at module scope.
Signed-off-by: SPEC <zt1y17@soton.ac.uk>
* fix(memory): close remaining cancel races from review
Post-clear cancel, legacy-only all_agents scope, always cancel even when
memory is disabled, and fold cancel+delete into one offloaded thread.
Signed-off-by: SPEC <zt1y17@soton.ac.uk>
* docs(memory): align cancel_by_agent None-scope with legacy root
Document that user_id=None cancels only the legacy no-user bucket, matching
clear/storage semantics, not the whole process-local queue.
Signed-off-by: SPEC <zt1y17@soton.ac.uk>
* test(memory): fix cancel_by_agent docstring regression assertion
Signed-off-by: SPEC <zt1y17@soton.ac.uk>
* fix(memory): address final cancel review nits
Type the delete helper with AgentStore, replace docstring pinning with a
kwargs mapping test, and document scoped cancel + residual window in AGENTS.md.
Signed-off-by: SPEC <zt1y17@soton.ac.uk>
* fix(memory): resolve agent store inside delete worker thread
get_agent_store() does blocking config/FS work; keep it off the event
loop so test_delete_agent_does_not_block_event_loop and backend-blocking-io CI pass.
Signed-off-by: SPEC <zt1y17@soton.ac.uk>
---------
Signed-off-by: SPEC <zt1y17@soton.ac.uk>
* docs: govern agent guidance size
* refactor: split agent guidance by code scope
* Clarify virtual path handling in AGENTS.md
Updated the translation section to clarify the role of `LocalSandboxProvider` and the handling of virtual paths in the tool layer.
---------
Co-authored-by: Willem Jiang <willem.jiang@gmail.com>