66from langchain_core .tools import StructuredTool
77
88from .base import Skill
9+ from ..config import MAX_RETRIES
910
1011
1112class RunScriptInput (BaseModel ):
@@ -15,17 +16,29 @@ class RunScriptInput(BaseModel):
1516class RunnerSkill (Skill ):
1617 """Provides the run_script tool."""
1718
19+ def __init__ (self , config , archive ):
20+ super ().__init__ (config , archive )
21+ self ._run_count = 0
22+ self ._max_runs = config .max_retries + 1 # initial run + retries
23+
1824 def get_tools (self ):
1925 work_dir = self .archive .work_dir
2026 archive = self .archive
2127 timeout = self .config .script_timeout
28+ skill = self
2229
2330 async def run_script_tool (script_name : str ) -> str :
31+ skill ._run_count += 1
32+ if skill ._run_count > skill ._max_runs :
33+ msg = f"RUN LIMIT REACHED ({ skill ._max_runs } runs). Stop and report the current status to the user."
34+ print (f"\n { msg } " , flush = True )
35+ return msg
36+
2437 script_path = work_dir / script_name
2538 if not script_path .exists ():
2639 return f"ERROR: Script '{ script_name } ' not found"
2740
28- print (f"\n Running { script_name } ..." , flush = True )
41+ print (f"\n Running { script_name } ... (run { skill . _run_count } / { skill . _max_runs } ) " , flush = True )
2942 try :
3043 result = subprocess .run (
3144 ["python" , script_name ],
@@ -45,10 +58,12 @@ async def run_script_tool(script_name: str) -> str:
4558 )
4659 print (f"Failed (code { result .returncode } )" , flush = True )
4760 archive .archive_run_output (error_msg )
61+ remaining = skill ._max_runs - skill ._run_count
4862 return (
4963 f"FAILED (code { result .returncode } )\n "
5064 f"Stderr:\n { result .stderr } \n "
51- f"Stdout:\n { result .stdout [:500 ]} "
65+ f"Stdout:\n { result .stdout [:500 ]} \n "
66+ f"\n You have { remaining } run(s) remaining."
5267 )
5368 except subprocess .TimeoutExpired :
5469 return f"ERROR: Script timed out ({ timeout } s)"
0 commit comments