@@ -63,10 +63,12 @@ def _load_task_config(task_dir: Path) -> dict:
6363 with open (config_path , "rb" ) as f :
6464 config = tomllib .load (f )
6565
66- docker_image = (config .get ("environment" ) or {}).get ("docker_image" , "ubuntu:22.04" )
66+ env = config .get ("environment" ) or {}
67+ docker_image = env .get ("docker_image" , "ubuntu:22.04" )
6768 problem_statement = instruction_path .read_text () if instruction_path .exists () else ""
6869 agent_timeout = (config .get ("agent" ) or {}).get ("timeout_sec" , None )
6970 verifier_timeout = (config .get ("verifier" ) or {}).get ("timeout_sec" , None )
71+ resources = _parse_env_resources (env )
7072
7173 # Parse last WORKDIR from Dockerfile (if present).
7274 workdir = None
@@ -82,6 +84,38 @@ def _load_task_config(task_dir: Path) -> dict:
8284 "agent_timeout_sec" : agent_timeout ,
8385 "verifier_timeout_sec" : verifier_timeout ,
8486 "workdir" : workdir ,
87+ ** resources ,
88+ }
89+
90+
91+ def _mem_to_mb (val ) -> int | None :
92+ """Normalize a memory/storage spec to MB. Accepts an int (already MB, e.g. ``memory_mb``)
93+ or a string with a unit (``"2G"``, ``"512M"``, ``"10G"``)."""
94+ if val is None :
95+ return None
96+ if isinstance (val , (int , float )):
97+ return int (val )
98+ s = str (val ).strip ().upper ().rstrip ("B" )
99+ units = {"K" : 1 / 1024 , "M" : 1.0 , "G" : 1024.0 , "T" : 1024.0 * 1024 }
100+ if s and s [- 1 ] in units :
101+ return int (float (s [:- 1 ]) * units [s [- 1 ]])
102+ return int (float (s )) # bare number → assume MB
103+
104+
105+ def _parse_env_resources (env : dict ) -> dict :
106+ """Pull cpu/memory/storage/gpu limits from a task.toml ``[environment]`` table, tolerating
107+ both schema v1.0 (``memory = "2G"``) and v1.1 (``memory_mb = 2048``)."""
108+ memory_mb = env .get ("memory_mb" )
109+ if memory_mb is None :
110+ memory_mb = _mem_to_mb (env .get ("memory" ))
111+ storage_mb = env .get ("storage_mb" )
112+ if storage_mb is None :
113+ storage_mb = _mem_to_mb (env .get ("storage" ))
114+ return {
115+ "cpus" : env .get ("cpus" ),
116+ "memory_mb" : memory_mb ,
117+ "storage_mb" : storage_mb ,
118+ "gpus" : env .get ("gpus" , 0 ),
85119 }
86120
87121
@@ -129,6 +163,10 @@ def _to_gym_row(task_dir: Path, task_cfg: dict) -> dict:
129163 if task_cfg .get ("verifier_timeout_sec" ) is not None
130164 else None ,
131165 "workdir" : task_cfg .get ("workdir" ),
166+ "cpus" : str (task_cfg ["cpus" ]) if task_cfg .get ("cpus" ) is not None else None ,
167+ "memory_mb" : str (task_cfg ["memory_mb" ]) if task_cfg .get ("memory_mb" ) is not None else None ,
168+ "storage_mb" : str (task_cfg ["storage_mb" ]) if task_cfg .get ("storage_mb" ) is not None else None ,
169+ "gpus" : str (task_cfg ["gpus" ]) if task_cfg .get ("gpus" ) is not None else None ,
132170 },
133171 },
134172 }
0 commit comments