fixed bug in check terminal requirements for slot pool

This commit is contained in:
Shannon Sands 2026-02-10 09:22:22 +00:00
parent 62001e3bf5
commit 3951eab399
4 changed files with 41 additions and 19 deletions

View file

@ -31,8 +31,11 @@ def _require_atroposlib() -> None:
_require_atroposlib()
# Re-export the most commonly used pieces for convenience.
# Agent imports are eager (always available).
from .agent import AgentConfig, AgentResult, AgentStep, AtroposAgent, SequenceData # noqa: E402
from .envs import AgentEnv, AgentEnvConfig # noqa: E402
# Env imports are lazy to avoid pulling in deleted atropos.tools dependencies.
# Use: from atropos.envs import AgentEnv, AgentEnvConfig (if needed)
__all__ = [
"AtroposAgent",
@ -40,7 +43,5 @@ __all__ = [
"AgentResult",
"AgentStep",
"SequenceData",
"AgentEnv",
"AgentEnvConfig",
]

View file

@ -1,10 +1,18 @@
"""
Environment implementations for atropos-agent.
NOTE: AgentEnv is the OLD environment system, replaced by
environments/hermes_base_env.py (HermesAgentBaseEnv).
Import is lazy to avoid pulling in deleted dependencies.
"""
from .agent_env import AgentEnv, AgentEnvConfig
# NOTE: Additional example envs exist as modules (e.g. `test_env`, `swe_smith_oracle_env`),
# but are intentionally not imported here to avoid pulling heavy optional deps at import time.
def __getattr__(name):
"""Lazy import to avoid breaking when old dependencies are removed."""
if name in ("AgentEnv", "AgentEnvConfig"):
from .agent_env import AgentEnv, AgentEnvConfig
return {"AgentEnv": AgentEnv, "AgentEnvConfig": AgentEnvConfig}[name]
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
__all__ = ["AgentEnv", "AgentEnvConfig"]

View file

@ -332,8 +332,13 @@ class HermesAgentBaseEnv(BaseEnv):
os.environ.setdefault("TERMINAL_NOMAD_MIN", str(self.config.min_containers))
os.environ.setdefault("TERMINAL_NOMAD_MAX", str(self.config.max_containers))
# Eagerly start the _SlotPoolManager so the backend is ready
# before any trajectories try to use it
from tools.terminal_tool import _SlotPoolManager
_SlotPoolManager.get_instance() # Triggers _start() which creates sandboxes
self._sandbox_backend = True # Flag that sandbox mode is active
print(f"🔧 Slot pool configured: TERMINAL_ENV=slot_pool, backend={mode}")
print(f"🔧 Slot pool started: TERMINAL_ENV=slot_pool, backend={mode}")
async def _stop_sandbox_backend(self) -> None:
"""Stop the slot pool backend."""
@ -710,18 +715,27 @@ class HermesAgentBaseEnv(BaseEnv):
logger.info("Sandbox slot acquired for task %s", task_id)
# 2. Create exec_tool for setup/verify hooks
# Routes through _SlotPoolManager (same slot as terminal_tool)
# Routes through handle_function_call → terminal_tool → same _SlotPoolEnvironment
async def exec_tool(tool_name: str, args: Dict[str, Any], timeout: float = 300) -> _ExecResult:
command = args.get("command", "")
result_dict = _SlotPoolManager.get_instance().execute(
task_id, command, timeout=timeout
result_json = await loop.run_in_executor(
None,
lambda: handle_function_call(
"terminal",
{"command": command, "timeout": int(timeout)},
task_id=task_id,
),
)
returncode = result_dict.get("returncode", 1)
try:
result_dict = json.loads(result_json)
except (json.JSONDecodeError, TypeError):
result_dict = {"output": str(result_json), "exit_code": 1}
returncode = result_dict.get("exit_code", result_dict.get("returncode", 1))
output = result_dict.get("output", "")
return _ExecResult(
success=(returncode == 0),
output=output,
error="" if returncode == 0 else f"Exit code: {returncode}",
error=result_dict.get("error", "") if returncode != 0 else "",
metadata={"returncode": returncode},
)

View file

@ -2411,17 +2411,14 @@ def check_terminal_requirements() -> bool:
try:
if env_type == "local":
from minisweagent.environments.local import LocalEnvironment
return True
elif env_type == "docker":
from minisweagent.environments.docker import DockerEnvironment
# Check if docker is available
# check actually available..
import subprocess
result = subprocess.run(["docker", "version"], capture_output=True, timeout=5)
return result.returncode == 0
elif env_type == "singularity":
from minisweagent.environments.singularity import SingularityEnvironment
# Check if singularity/apptainer is available
# Check if singularity/apptainer is available (doesn't work on mac)
import subprocess
import shutil
executable = shutil.which("apptainer") or shutil.which("singularity")
@ -2430,9 +2427,11 @@ def check_terminal_requirements() -> bool:
return result.returncode == 0
return False
elif env_type == "modal":
from minisweagent.environments.extra.swerex_modal import SwerexModalEnvironment
# Check for modal token
# check modal is actually configured
return os.getenv("MODAL_TOKEN_ID") is not None or Path.home().joinpath(".modal.toml").exists()
elif env_type == "slot_pool":
# Slot pool uses atropos/backends/ & always available if modal/nomad is configured
return True
else:
return False
except Exception as e: