@@ -171,6 +171,12 @@ def parse_args():
171171 action = "store_true" ,
172172 help = "Disable sending update feedback to server" ,
173173 )
174+ parser .add_argument (
175+ "--test_mode" ,
176+ action = "store_true" ,
177+ default = False ,
178+ help = "Test mode: all actions simulate execution and return mock results without running real hardware" ,
179+ )
174180 # workflow upload subcommand
175181 workflow_parser = subparsers .add_parser (
176182 "workflow_upload" ,
@@ -204,6 +210,12 @@ def parse_args():
204210 default = False ,
205211 help = "Whether to publish the workflow (default: False)" ,
206212 )
213+ workflow_parser .add_argument (
214+ "--description" ,
215+ type = str ,
216+ default = "" ,
217+ help = "Workflow description, used when publishing the workflow" ,
218+ )
207219 return parser
208220
209221
@@ -231,52 +243,60 @@ def main():
231243 # 加载配置文件,优先加载config,然后从env读取
232244 config_path = args_dict .get ("config" )
233245
234- if check_mode :
235- args_dict ["working_dir" ] = os .path .abspath (os .getcwd ())
236- # 当 skip_env_check 时,默认使用当前目录作为 working_dir
237- if skip_env_check and not args_dict .get ("working_dir" ) and not config_path :
246+ # === 解析 working_dir ===
247+ # 规则1: working_dir 传入 → 检测 unilabos_data 子目录,已是则不修改
248+ # 规则2: 仅 config_path 传入 → 用其父目录作为 working_dir
249+ # 规则4: 两者都传入 → 各用各的,但 working_dir 仍做 unilabos_data 子目录检测
250+ raw_working_dir = args_dict .get ("working_dir" )
251+ if raw_working_dir :
252+ working_dir = os .path .abspath (raw_working_dir )
253+ elif config_path and os .path .exists (config_path ):
254+ working_dir = os .path .dirname (os .path .abspath (config_path ))
255+ else :
238256 working_dir = os .path .abspath (os .getcwd ())
239- print_status (f"跳过环境检查模式:使用当前目录作为工作目录 { working_dir } " , "info" )
240- # 检查当前目录是否有 local_config.py
241- local_config_in_cwd = os .path .join (working_dir , "local_config.py" )
242- if os .path .exists (local_config_in_cwd ):
243- config_path = local_config_in_cwd
257+
258+ # unilabos_data 子目录自动检测
259+ if os .path .basename (working_dir ) != "unilabos_data" :
260+ unilabos_data_sub = os .path .join (working_dir , "unilabos_data" )
261+ if os .path .isdir (unilabos_data_sub ):
262+ working_dir = unilabos_data_sub
263+ elif not raw_working_dir and not (config_path and os .path .exists (config_path )):
264+ # 未显式指定路径,默认使用 cwd/unilabos_data
265+ working_dir = os .path .abspath (os .path .join (os .getcwd (), "unilabos_data" ))
266+
267+ # === 解析 config_path ===
268+ if config_path and not os .path .exists (config_path ):
269+ # config_path 传入但不存在,尝试在 working_dir 中查找
270+ candidate = os .path .join (working_dir , "local_config.py" )
271+ if os .path .exists (candidate ):
272+ config_path = candidate
273+ print_status (f"在工作目录中发现配置文件: { config_path } " , "info" )
274+ else :
275+ print_status (
276+ f"配置文件 { config_path } 不存在,工作目录 { working_dir } 中也未找到 local_config.py,"
277+ f"请通过 --config 传入 local_config.py 文件路径" ,
278+ "error" ,
279+ )
280+ os ._exit (1 )
281+ elif not config_path :
282+ # 规则3: 未传入 config_path,尝试 working_dir/local_config.py
283+ candidate = os .path .join (working_dir , "local_config.py" )
284+ if os .path .exists (candidate ):
285+ config_path = candidate
244286 print_status (f"发现本地配置文件: { config_path } " , "info" )
245287 else :
246288 print_status (f"未指定config路径,可通过 --config 传入 local_config.py 文件路径" , "info" )
247- elif os .getcwd ().endswith ("unilabos_data" ):
248- working_dir = os .path .abspath (os .getcwd ())
249- else :
250- working_dir = os .path .abspath (os .path .join (os .getcwd (), "unilabos_data" ))
251-
252- if args_dict .get ("working_dir" ):
253- working_dir = args_dict .get ("working_dir" , "" )
254- if config_path and not os .path .exists (config_path ):
255- config_path = os .path .join (working_dir , "local_config.py" )
256- if not os .path .exists (config_path ):
257- print_status (
258- f"当前工作目录 { working_dir } 未找到local_config.py,请通过 --config 传入 local_config.py 文件路径" ,
259- "error" ,
289+ print_status (f"您是否为第一次使用?并将当前路径 { working_dir } 作为工作目录? (Y/n)" , "info" )
290+ if check_mode or input () != "n" :
291+ os .makedirs (working_dir , exist_ok = True )
292+ config_path = os .path .join (working_dir , "local_config.py" )
293+ shutil .copy (
294+ os .path .join (os .path .dirname (os .path .dirname (__file__ )), "config" , "example_config.py" ),
295+ config_path ,
260296 )
297+ print_status (f"已创建 local_config.py 路径: { config_path } " , "info" )
298+ else :
261299 os ._exit (1 )
262- elif config_path and os .path .exists (config_path ):
263- working_dir = os .path .dirname (config_path )
264- elif os .path .exists (working_dir ) and os .path .exists (os .path .join (working_dir , "local_config.py" )):
265- config_path = os .path .join (working_dir , "local_config.py" )
266- elif not skip_env_check and not config_path and (
267- not os .path .exists (working_dir ) or not os .path .exists (os .path .join (working_dir , "local_config.py" ))
268- ):
269- print_status (f"未指定config路径,可通过 --config 传入 local_config.py 文件路径" , "info" )
270- print_status (f"您是否为第一次使用?并将当前路径 { working_dir } 作为工作目录? (Y/n)" , "info" )
271- if input () != "n" :
272- os .makedirs (working_dir , exist_ok = True )
273- config_path = os .path .join (working_dir , "local_config.py" )
274- shutil .copy (
275- os .path .join (os .path .dirname (os .path .dirname (__file__ )), "config" , "example_config.py" ), config_path
276- )
277- print_status (f"已创建 local_config.py 路径: { config_path } " , "info" )
278- else :
279- os ._exit (1 )
280300
281301 # 加载配置文件 (check_mode 跳过)
282302 print_status (f"当前工作目录为 { working_dir } " , "info" )
@@ -288,7 +308,9 @@ def main():
288308
289309 if hasattr (BasicConfig , "log_level" ):
290310 logger .info (f"Log level set to '{ BasicConfig .log_level } ' from config file." )
291- configure_logger (loglevel = BasicConfig .log_level , working_dir = working_dir )
311+ file_path = configure_logger (loglevel = BasicConfig .log_level , working_dir = working_dir )
312+ if file_path is not None :
313+ logger .info (f"[LOG_FILE] { file_path } " )
292314
293315 if args .addr != parser .get_default ("addr" ):
294316 if args .addr == "test" :
@@ -332,6 +354,9 @@ def main():
332354 BasicConfig .slave_no_host = args_dict .get ("slave_no_host" , False )
333355 BasicConfig .upload_registry = args_dict .get ("upload_registry" , False )
334356 BasicConfig .no_update_feedback = args_dict .get ("no_update_feedback" , False )
357+ BasicConfig .test_mode = args_dict .get ("test_mode" , False )
358+ if BasicConfig .test_mode :
359+ print_status ("启用测试模式:所有动作将模拟执行,不调用真实硬件" , "warning" )
335360 BasicConfig .communication_protocol = "websocket"
336361 machine_name = os .popen ("hostname" ).read ().strip ()
337362 machine_name = "" .join ([c if c .isalnum () or c == "_" else "_" for c in machine_name ])
0 commit comments