@@ -157,9 +157,8 @@ async def file_upload(self, file_path: str):
157157 async def is_docker_available (self ) -> bool :
158158 """Check if docker is available"""
159159 try :
160- docker = aiodocker .Docker ()
161- await docker .version ()
162- await docker .close ()
160+ async with aiodocker .Docker () as docker :
161+ await docker .version ()
163162 return True
164163 except BaseException as e :
165164 logger .info (f"检查 Docker 可用性: { e } " )
@@ -279,14 +278,14 @@ async def pi_mirror(self, event: AstrMessageEvent, url: str = ""):
279278 @pi .command ("repull" )
280279 async def pi_repull (self , event : AstrMessageEvent ):
281280 """重新拉取沙箱镜像"""
282- docker = aiodocker .Docker ()
283- image_name = await self .get_image_name ()
284- try :
285- await docker .images .get (image_name )
286- await docker .images .delete (image_name , force = True )
287- except aiodocker .exceptions .DockerError :
288- pass
289- await docker .images .pull (image_name )
281+ async with aiodocker .Docker () as docker :
282+ image_name = await self .get_image_name ()
283+ try :
284+ await docker .images .get (image_name )
285+ await docker .images .delete (image_name , force = True )
286+ except aiodocker .exceptions .DockerError :
287+ pass
288+ await docker .images .pull (image_name )
290289 yield event .plain_result ("重新拉取沙箱镜像成功。" )
291290
292291 @pi .command ("file" )
@@ -371,137 +370,137 @@ async def python_interpreter(self, event: AstrMessageEvent):
371370 obs = ""
372371 n = 5
373372
374- for i in range (n ):
375- if i > 0 :
376- logger .info (f"Try { i + 1 } /{ n } " )
377-
378- PROMPT_ = PROMPT .format (
379- prompt = plain_text ,
380- extra_input = extra_inputs ,
381- extra_prompt = obs ,
382- )
383- provider = self .context .get_using_provider ()
384- llm_response = await provider .text_chat (
385- prompt = PROMPT_ ,
386- session_id = f"{ event .session_id } _{ magic_code } _{ i !s} " ,
387- )
388-
389- logger .debug (
390- "code interpreter llm gened code:" + llm_response .completion_text ,
391- )
392-
393- # 整理代码并保存
394- code_clean = await self .tidy_code (llm_response .completion_text )
395- with open (os .path .join (workplace_path , "exec.py" ), "w" ) as f :
396- f .write (code_clean )
397-
398- # 启动容器
399- docker = aiodocker .Docker ()
400-
401- # 检查有没有image
402- image_name = await self .get_image_name ()
403- try :
404- await docker .images .get (image_name )
405- except aiodocker .exceptions .DockerError :
406- # 拉取镜像
407- logger .info (f"未找到沙箱镜像,正在尝试拉取 { image_name } ..." )
408- await docker .images .pull (image_name )
373+ async with aiodocker .Docker () as docker :
374+ for i in range (n ):
375+ if i > 0 :
376+ logger .info (f"Try { i + 1 } /{ n } " )
409377
410- yield event .plain_result (
411- f"使用沙箱执行代码中,请稍等...(尝试次数: { i + 1 } /{ n } )" ,
412- )
378+ PROMPT_ = PROMPT .format (
379+ prompt = plain_text ,
380+ extra_input = extra_inputs ,
381+ extra_prompt = obs ,
382+ )
383+ provider = self .context .get_using_provider ()
384+ llm_response = await provider .text_chat (
385+ prompt = PROMPT_ ,
386+ session_id = f"{ event .session_id } _{ magic_code } _{ i !s} " ,
387+ )
413388
414- self .docker_host_astrbot_abs_path = self .config .get (
415- "docker_host_astrbot_abs_path" ,
416- "" ,
417- )
418- if self .docker_host_astrbot_abs_path :
419- host_shared = os .path .join (
420- self .docker_host_astrbot_abs_path ,
421- self .shared_path ,
389+ logger .debug (
390+ "code interpreter llm gened code:" + llm_response .completion_text ,
422391 )
423- host_output = os .path .join (
424- self .docker_host_astrbot_abs_path ,
425- output_path ,
392+
393+ # 整理代码并保存
394+ code_clean = await self .tidy_code (llm_response .completion_text )
395+ with open (os .path .join (workplace_path , "exec.py" ), "w" ) as f :
396+ f .write (code_clean )
397+
398+ # 检查有没有image
399+ image_name = await self .get_image_name ()
400+ try :
401+ await docker .images .get (image_name )
402+ except aiodocker .exceptions .DockerError :
403+ # 拉取镜像
404+ logger .info (f"未找到沙箱镜像,正在尝试拉取 { image_name } ..." )
405+ await docker .images .pull (image_name )
406+
407+ yield event .plain_result (
408+ f"使用沙箱执行代码中,请稍等...(尝试次数: { i + 1 } /{ n } )" ,
426409 )
427- host_workplace = os .path .join (
428- self .docker_host_astrbot_abs_path ,
429- workplace_path ,
410+
411+ self .docker_host_astrbot_abs_path = self .config .get (
412+ "docker_host_astrbot_abs_path" ,
413+ "" ,
430414 )
415+ if self .docker_host_astrbot_abs_path :
416+ host_shared = os .path .join (
417+ self .docker_host_astrbot_abs_path ,
418+ self .shared_path ,
419+ )
420+ host_output = os .path .join (
421+ self .docker_host_astrbot_abs_path ,
422+ output_path ,
423+ )
424+ host_workplace = os .path .join (
425+ self .docker_host_astrbot_abs_path ,
426+ workplace_path ,
427+ )
431428
432- else :
433- host_shared = os .path .abspath (self .shared_path )
434- host_output = os .path .abspath (output_path )
435- host_workplace = os .path .abspath (workplace_path )
429+ else :
430+ host_shared = os .path .abspath (self .shared_path )
431+ host_output = os .path .abspath (output_path )
432+ host_workplace = os .path .abspath (workplace_path )
436433
437- logger .debug (
438- f"host_shared: { host_shared } , host_output: { host_output } , host_workplace: { host_workplace } " ,
439- )
434+ logger .debug (
435+ f"host_shared: { host_shared } , host_output: { host_output } , host_workplace: { host_workplace } " ,
436+ )
440437
441- container = await docker .containers .run (
442- {
443- "Image" : image_name ,
444- "Cmd" : ["python" , "exec.py" ],
445- "Memory" : 512 * 1024 * 1024 ,
446- "NanoCPUs" : 1000000000 ,
447- "HostConfig" : {
448- "Binds" : [
449- f"{ host_shared } :/astrbot_sandbox/shared:ro" ,
450- f"{ host_output } :/astrbot_sandbox/output:rw" ,
451- f"{ host_workplace } :/astrbot_sandbox:rw" ,
452- ],
438+ container = await docker .containers .run (
439+ {
440+ "Image" : image_name ,
441+ "Cmd" : ["python" , "exec.py" ],
442+ "Memory" : 512 * 1024 * 1024 ,
443+ "NanoCPUs" : 1000000000 ,
444+ "HostConfig" : {
445+ "Binds" : [
446+ f"{ host_shared } :/astrbot_sandbox/shared:ro" ,
447+ f"{ host_output } :/astrbot_sandbox/output:rw" ,
448+ f"{ host_workplace } :/astrbot_sandbox:rw" ,
449+ ],
450+ },
451+ "Env" : [f"MAGIC_CODE={ magic_code } " ],
452+ "AutoRemove" : True ,
453453 },
454- "Env" : [f"MAGIC_CODE={ magic_code } " ],
455- "AutoRemove" : True ,
456- },
457- )
454+ )
458455
459- logger .debug (f"Container { container .id } created." )
460- logs = await self .run_container (container )
461-
462- logger .debug (f"Container { container .id } finished." )
463- logger .debug (f"Container { container .id } logs: { logs } " )
464-
465- # 发送结果
466- pattern = r"\[ASTRBOT_(TEXT|IMAGE|FILE)_OUTPUT#\w+\]: (.*)"
467- ok = False
468- traceback = ""
469- for idx , log in enumerate (logs ):
470- match = re .match (pattern , log )
471- if match :
472- ok = True
473- if match .group (1 ) == "TEXT" :
474- yield event .plain_result (match .group (2 ))
475- elif match .group (1 ) == "IMAGE" :
476- image_path = os .path .join (workplace_path , match .group (2 ))
477- logger .debug (f"Sending image: { image_path } " )
478- yield event .image_result (image_path )
479- elif match .group (1 ) == "FILE" :
480- file_path = os .path .join (workplace_path , match .group (2 ))
481- # logger.debug(f"Sending file: {file_path}")
482- # file_s3_url = await self.file_upload(file_path)
483- # logger.info(f"文件上传到 AstrBot 云节点: {file_s3_url}")
484- file_name = os .path .basename (file_path )
485- chain : list [BaseMessageComponent ] = [
486- File (name = file_name , file = file_path )
487- ]
488- yield event .set_result (MessageEventResult (chain = chain ))
489-
490- elif "Traceback (most recent call last)" in log or "[Error]: " in log :
491- traceback = "\n " .join (logs [idx :])
492-
493- if not ok :
494- if traceback :
495- obs = f"## Observation \n When execute the code: ```python\n { code_clean } \n ```\n \n Error occurred:\n \n { traceback } \n Need to improve/fix the code."
456+ logger .debug (f"Container { container .id } created." )
457+ logs = await self .run_container (container )
458+
459+ logger .debug (f"Container { container .id } finished." )
460+ logger .debug (f"Container { container .id } logs: { logs } " )
461+
462+ # 发送结果
463+ pattern = r"\[ASTRBOT_(TEXT|IMAGE|FILE)_OUTPUT#\w+\]: (.*)"
464+ ok = False
465+ traceback = ""
466+ for idx , log in enumerate (logs ):
467+ match = re .match (pattern , log )
468+ if match :
469+ ok = True
470+ if match .group (1 ) == "TEXT" :
471+ yield event .plain_result (match .group (2 ))
472+ elif match .group (1 ) == "IMAGE" :
473+ image_path = os .path .join (workplace_path , match .group (2 ))
474+ logger .debug (f"Sending image: { image_path } " )
475+ yield event .image_result (image_path )
476+ elif match .group (1 ) == "FILE" :
477+ file_path = os .path .join (workplace_path , match .group (2 ))
478+ # logger.debug(f"Sending file: {file_path}")
479+ # file_s3_url = await self.file_upload(file_path)
480+ # logger.info(f"文件上传到 AstrBot 云节点: {file_s3_url}")
481+ file_name = os .path .basename (file_path )
482+ chain : list [BaseMessageComponent ] = [
483+ File (name = file_name , file = file_path )
484+ ]
485+ yield event .set_result (MessageEventResult (chain = chain ))
486+
487+ elif (
488+ "Traceback (most recent call last)" in log or "[Error]: " in log
489+ ):
490+ traceback = "\n " .join (logs [idx :])
491+
492+ if not ok :
493+ if traceback :
494+ obs = f"## Observation \n When execute the code: ```python\n { code_clean } \n ```\n \n Error occurred:\n \n { traceback } \n Need to improve/fix the code."
495+ else :
496+ logger .warning (
497+ f"未从沙箱输出中捕获到合法的输出。沙箱输出日志: { logs } " ,
498+ )
499+ break
496500 else :
497- logger .warning (
498- f"未从沙箱输出中捕获到合法的输出。沙箱输出日志: { logs } " ,
499- )
500- break
501- else :
502- # 成功了
503- self .user_file_msg_buffer .pop (event .get_session_id ())
504- return
501+ # 成功了
502+ self .user_file_msg_buffer .pop (event .get_session_id ())
503+ return
505504
506505 yield event .plain_result (
507506 "经过多次尝试后,未从沙箱输出中捕获到合法的输出,请更换问法或者查看日志。" ,
0 commit comments