Reuse dead VM names in sandbox auto-naming

This commit is contained in:
Ryan Malloy 2026-08-17 00:32:32 -06:00
parent f3c5e2ce48
commit ea0deb8e70
2 changed files with 24 additions and 5 deletions

View File

@ -25,11 +25,19 @@ async def _agent_responding(record) -> bool:
return False
def _auto_name(taken: list[str]) -> str:
if "sandbox" not in taken:
def _auto_name(registry) -> str:
"""First 'sandbox[-N]' name that is unregistered or belongs to a dead VM
(launch_vm reclaims dead names, so reusing them is safe and keeps names
predictable)."""
def usable(candidate: str) -> bool:
record = registry.get(candidate)
return record is None or not registry.is_process_alive(record)
if usable("sandbox"):
return "sandbox"
i = 2
while f"sandbox-{i}" in taken:
while not usable(f"sandbox-{i}"):
i += 1
return f"sandbox-{i}"
@ -57,7 +65,7 @@ async def sandbox_vm(
raise ToolError(f"Bad base image: {e}") from e
if name is None:
name = _auto_name(state.registry.names())
name = _auto_name(state.registry)
elif not valid_vm_name(name):
raise ToolError(
f"Invalid VM name {name!r}: use letters, digits, '.', '_', '-' (max 48 chars)."

View File

@ -99,13 +99,24 @@ async def test_sandbox_vm_creates_overlay_and_waits(dirs, base_image, fake_launc
assert data["overlay"] == str(overlay)
async def test_sandbox_auto_names_avoid_collisions(dirs, base_image, fake_launch, agent_up):
async def test_sandbox_auto_names_avoid_live_collisions(
dirs, base_image, fake_launch, agent_up, all_pids_alive
):
write_registry(dirs, seeded_record(dirs, "sandbox"))
async with Client(mcp) as client:
data = result_data(await client.call_tool("sandbox_vm", {"base_image": str(base_image)}))
assert data["name"] == "sandbox-2"
async def test_sandbox_auto_name_reuses_dead(
dirs, base_image, fake_launch, agent_up, all_pids_dead
):
write_registry(dirs, seeded_record(dirs, "sandbox"))
async with Client(mcp) as client:
data = result_data(await client.call_tool("sandbox_vm", {"base_image": str(base_image)}))
assert data["name"] == "sandbox"
async def test_sandbox_agent_timeout_reports_hint(dirs, base_image, fake_launch, monkeypatch):
async def never(record):
return False