Spaces:
Sleeping
Sleeping
| from tools_runtime import execute_tool_call | |
| from self_heal import SelfHealer | |
| import shlex | |
| class Executor: | |
| def __init__(self, llm=None): | |
| self.llm = llm | |
| self.healer = SelfHealer(llm=llm) | |
| # ===================================================== | |
| # MAIN PIPELINE | |
| # ===================================================== | |
| def run_plan(self, plan): | |
| if not isinstance(plan, dict): | |
| return {"error": "Plan must be dict"} | |
| steps = plan.get("steps", []) | |
| if not isinstance(steps, list): | |
| return {"error": "Invalid steps format"} | |
| results = [] | |
| for step in steps: | |
| print(f"🚀 Executing step: {step}") | |
| # STEP 1: convert to action | |
| action = self._interpret_step(step) | |
| # STEP 2: execute tool | |
| tool_result = self._execute_tool(action) | |
| # STEP 3: self-heal (safe retry) | |
| tool_result = self._safe_heal(step, tool_result) | |
| # STEP 4: optional LLM analysis | |
| llm_result = self._llm_analyze(step, action, tool_result) | |
| # STEP 5: store | |
| results.append({ | |
| "step": step, | |
| "action": action, | |
| "tool_result": tool_result, | |
| "llm_result": llm_result | |
| }) | |
| return { | |
| "status": "completed", | |
| "results": results | |
| } | |
| # ===================================================== | |
| # STEP INTERPRETER (FIXED - NO NOOP TRAP) | |
| # ===================================================== | |
| def _interpret_step(self, step): | |
| # already structured tool | |
| if isinstance(step, dict): | |
| return step | |
| if not isinstance(step, str): | |
| return { | |
| "tool": "run_shell", | |
| "args": {"cmd": "echo invalid_step"} | |
| } | |
| cmd = step.strip() | |
| if not cmd: | |
| return { | |
| "tool": "run_shell", | |
| "args": {"cmd": "echo empty_step"} | |
| } | |
| # 🔥 IMPORTANT FIX: | |
| # DO NOT block natural language anymore | |
| # Instead: ALWAYS convert to shell-safe fallback | |
| shell_like = self._looks_like_shell(cmd) | |
| if shell_like: | |
| return { | |
| "tool": "run_shell", | |
| "args": { | |
| "cmd": cmd | |
| } | |
| } | |
| # fallback: convert to safe echo (never noop) | |
| return { | |
| "tool": "run_shell", | |
| "args": { | |
| "cmd": f"echo '[interpreted step] {shlex.quote(cmd)}'" | |
| } | |
| } | |
| # ===================================================== | |
| # SIMPLE HEURISTIC (NOT BLOCKING) | |
| # ===================================================== | |
| def _looks_like_shell(self, cmd: str): | |
| shell_signals = [ | |
| "ls", "cd", "mkdir", "touch", | |
| "python", "pip", "rm", "echo", | |
| "./", "git", "npm", "curl" | |
| ] | |
| first = cmd.split()[0].lower() if cmd.split() else "" | |
| return first in shell_signals | |
| # ===================================================== | |
| # TOOL EXECUTION | |
| # ===================================================== | |
| def _execute_tool(self, action): | |
| try: | |
| if not isinstance(action, dict): | |
| return {"error": "invalid_action"} | |
| return execute_tool_call(action) | |
| except Exception as e: | |
| return {"error": str(e)} | |
| # ===================================================== | |
| # SELF HEAL (SAFE RETRY ONLY) | |
| # ===================================================== | |
| def _safe_heal(self, step, tool_result): | |
| try: | |
| fix = self.healer.heal(step, tool_result) | |
| if isinstance(fix, dict) and "tool" in fix: | |
| print("🛠️ Self-healing triggered") | |
| return execute_tool_call(fix) | |
| except Exception as e: | |
| return { | |
| "error": f"healer_error: {str(e)}" | |
| } | |
| return tool_result | |
| # ===================================================== | |
| # LLM ANALYSIS (NO EXECUTION) | |
| # ===================================================== | |
| def _llm_analyze(self, step, action, tool_result): | |
| if not self.llm: | |
| return None | |
| try: | |
| response = self.llm([ | |
| { | |
| "role": "system", | |
| "content": "Analyze only. NEVER execute tools." | |
| }, | |
| { | |
| "role": "user", | |
| "content": f""" | |
| Step: {step} | |
| Action: {action} | |
| Result: {tool_result} | |
| """ | |
| } | |
| ]) | |
| if isinstance(response, dict): | |
| return ( | |
| response.get("choices", [{}])[0] | |
| .get("message", {}) | |
| .get("content", "LLM_EMPTY") | |
| ) | |
| return str(response) | |
| except Exception as e: | |
| return f"llm_error: {str(e)}" |