provider: add uv SandboxProvider (PR #122 stage C)#135
Merged
Conversation
Cherry-pick of efedacf from origin/abridge/gateway-tito (+ its ruff import-order hunk from 90f970a): a lightweight SandboxProvider at plugins/providers/uv that materializes a venv with uv and launches the runtime server as a local subprocess — for dev / eval / CI where container isolation isn't needed. Registered as entry point 'uv'; wired into pyright include/extraPaths (workspace membership via the existing plugins/providers/* glob). Fixes on top of the port (planned + adversarial review): - stdout drain: the runtime's merged stdout/stderr is drained for the sandbox's lifetime into a bounded tail (8x64KiB). Previously nothing read the pipe after health — asyncio flow control pauses at ~192KiB buffered, so a server that logged past that blocked mid-write and wedged every in-flight rollout. The tail also feeds the exited-before-health diagnostic (was a one-shot read). - that diagnostic path uses asyncio.wait, not wait_for — wait_for cancels the drain on timeout and delete()'s re-await then surfaced a bare CancelledError instead of the RuntimeError diagnostic (repro: a grandchild holding the pipe open past the 2s window). - ports are reserved in-process until the sandbox dies (same _inflight_ports guard as DockerProvider) — the subprocess binds the number seconds after allocation, so concurrent creates could collide: worst case two rollouts silently sharing one runtime. - a failed venv materialization removes its mkdtemp root (a retry loop leaked one partial venv per attempt). - the default uv binary resolves via uv.find_uv_bin() — the packaged wheel's binary is not on PATH under systemd/cron/absolute-path launches; a bare FileNotFoundError also now carries install guidance. - README/docstring examples close the provider (aclose is the only thing that removes a materialized venv). Tests: flood server proving the drain (pre-fix it wedges mid-write), grandchild-held pipe diagnostic, port-collision guard, temp-root cleanup, packaged-uv resolution off-PATH. Co-authored-by: FatPigeorz <wjhhhhhha0@gmail.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This was referenced Jul 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Third slice of the #122 split (stage map in the coordination comment; A = #133, B = #134). Cherry-picks the
UvProviderfromorigin/abridge/gateway-tito(efedacf + the ruff hunk from 90f970a), plus fixes from the pre-PR adversarial review.What's in
plugins/providers/uv— a lightweightSandboxProviderthat skips Docker/Nix entirely:uv venv+uv pip install -e <project>(orreuse_venv=), then the runtime server runs as a local subprocess. For dev / eval / CI where container isolation isn't needed; registered as entry pointuv.Fixes on top of the port
wait_for, which cancels the drain task on timeout;delete()'s re-await then surfaced a bareCancelledErrorinstead of theRuntimeErrorwith rc + log tail (reproduced with a grandchild holding the pipe open). Switched to non-cancellingasyncio.wait.create()s could collide (worst case: two rollouts silently sharing one runtime). Reserved in-process until the sandbox dies, mirroring DockerProvider's_inflight_ports.uv venv/uv pip installnow removes its mkdtemp root (a retry loop leaked one partial venv per attempt).uv.find_uv_bin()— the wheel's binary isn't on PATH under systemd/cron/absolute-path launches, exactly where no system uv exists; a bareFileNotFoundErrornow carries install guidance.provider.aclose()(the only thing that removes a materialized venv).Verification
uv run pytest tests/ plugins/— 496 passed (10 uv-provider tests: real subprocess servers via a fake-venv shim — flood/drain, grandchild-held pipe, port guard, temp cleanup, off-PATH resolution, plus the ported remote() round-trip)uv run ruff check ./uv run pyright— clean / 0 errors🤖 Generated with Claude Code