PYAE1994 commited on
Commit
c7fc003
·
verified ·
1 Parent(s): 4cf2b20

Update app/agent/executor.py

Browse files
Files changed (1) hide show
  1. app/agent/executor.py +82 -43
app/agent/executor.py CHANGED
@@ -26,14 +26,19 @@ class Executor:
26
 
27
  print(f"🚀 Executing step: {step}")
28
 
29
- # =========================
30
- # 1. TOOL EXECUTION LAYER
31
- # =========================
32
- tool_result = self._execute_as_tool(step)
33
-
34
- # =========================
35
- # 2. SELF HEAL (SAFE)
36
- # =========================
 
 
 
 
 
37
  try:
38
  fix = self.healer.heal(step, tool_result)
39
 
@@ -42,7 +47,6 @@ class Executor:
42
 
43
  healed = execute_tool_call(fix)
44
 
45
- # replace only if valid result
46
  if healed:
47
  tool_result = healed
48
 
@@ -51,9 +55,9 @@ class Executor:
51
  "error": f"healer_error: {str(e)}"
52
  }
53
 
54
- # =========================
55
- # 3. LLM ANALYSIS (NO EXECUTION)
56
- # =========================
57
  llm_result = None
58
 
59
  if self.llm:
@@ -62,13 +66,17 @@ class Executor:
62
  {
63
  "role": "system",
64
  "content": (
65
- "You are an analysis engine. "
66
- "NEVER execute tools. Only explain results."
67
  )
68
  },
69
  {
70
  "role": "user",
71
- "content": f"Step:\n{step}\n\nResult:\n{tool_result}"
 
 
 
 
72
  }
73
  ])
74
 
@@ -84,11 +92,12 @@ class Executor:
84
  except Exception as e:
85
  llm_result = f"llm_error: {str(e)}"
86
 
87
- # =========================
88
- # 4. STORE RESULT
89
- # =========================
90
  results.append({
91
  "step": step,
 
92
  "tool_result": tool_result,
93
  "llm_result": llm_result
94
  })
@@ -99,39 +108,69 @@ class Executor:
99
  }
100
 
101
  # =====================================================
102
- # SAFE TOOL EXECUTION WRAPPER
103
  # =====================================================
104
- def _execute_as_tool(self, step):
105
 
106
- try:
107
- # CASE 1: string → shell command
108
- if isinstance(step, str):
109
- cmd = step.strip()
110
-
111
- # block fake natural language commands
112
- blocked_words = ["create", "install", "open", "navigate", "save", "run"]
113
- if any(w in cmd.lower().split()[0] for w in blocked_words):
114
- return {
115
- "error": "Unsafe natural-language step rejected",
116
- "step": cmd
117
- }
118
 
119
- return execute_tool_call({
120
- "tool": "run_shell",
 
 
 
 
 
 
 
 
 
121
  "args": {
122
- "cmd": cmd
 
123
  }
124
- })
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125
 
126
- # CASE 2: tool dict
127
- if isinstance(step, dict):
 
 
128
 
129
- if "tool" not in step or "args" not in step:
130
- return {"error": "Invalid tool format"}
 
131
 
132
- return execute_tool_call(step)
 
 
 
 
133
 
134
- return {"error": "Unsupported step type"}
135
 
136
  except Exception as e:
137
- return {"error": str(e)}
 
 
 
26
 
27
  print(f"🚀 Executing step: {step}")
28
 
29
+ # =================================================
30
+ # STEP 1: NORMALIZE STEP (CRITICAL FIX)
31
+ # =================================================
32
+ action = self._interpret_step(step)
33
+
34
+ # =================================================
35
+ # STEP 2: EXECUTE TOOL ONLY
36
+ # =================================================
37
+ tool_result = self._execute_tool(action)
38
+
39
+ # =================================================
40
+ # STEP 3: SELF HEAL (SAFE)
41
+ # =================================================
42
  try:
43
  fix = self.healer.heal(step, tool_result)
44
 
 
47
 
48
  healed = execute_tool_call(fix)
49
 
 
50
  if healed:
51
  tool_result = healed
52
 
 
55
  "error": f"healer_error: {str(e)}"
56
  }
57
 
58
+ # =================================================
59
+ # STEP 4: LLM ANALYSIS ONLY (NO EXECUTION)
60
+ # =================================================
61
  llm_result = None
62
 
63
  if self.llm:
 
66
  {
67
  "role": "system",
68
  "content": (
69
+ "You are a code execution analyzer. "
70
+ "DO NOT execute anything. Only explain results."
71
  )
72
  },
73
  {
74
  "role": "user",
75
+ "content": f"""
76
+ Step: {step}
77
+ Action: {action}
78
+ Result: {tool_result}
79
+ """
80
  }
81
  ])
82
 
 
92
  except Exception as e:
93
  llm_result = f"llm_error: {str(e)}"
94
 
95
+ # =================================================
96
+ # STEP 5: STORE RESULT
97
+ # =================================================
98
  results.append({
99
  "step": step,
100
+ "action": action,
101
  "tool_result": tool_result,
102
  "llm_result": llm_result
103
  })
 
108
  }
109
 
110
  # =====================================================
111
+ # 🔥 CORE FIX: STEP INTERPRETER (IMPORTANT)
112
  # =====================================================
113
+ def _interpret_step(self, step):
114
 
115
+ # CASE 1: already structured tool
116
+ if isinstance(step, dict):
117
+ return step
118
+
119
+ # CASE 2: string → convert ONLY safe shell commands
120
+ if isinstance(step, str):
121
+
122
+ cmd = step.strip()
 
 
 
 
123
 
124
+ # ❌ block natural language completely
125
+ blocked_keywords = [
126
+ "create", "install", "open", "navigate",
127
+ "run", "save", "write", "make"
128
+ ]
129
+
130
+ first_word = cmd.lower().split()[0] if cmd.split() else ""
131
+
132
+ if first_word in blocked_keywords:
133
+ return {
134
+ "tool": "noop",
135
  "args": {
136
+ "reason": "natural_language_blocked",
137
+ "input": cmd
138
  }
139
+ }
140
+
141
+ # allow only real shell commands
142
+ return {
143
+ "tool": "run_shell",
144
+ "args": {
145
+ "cmd": cmd
146
+ }
147
+ }
148
+
149
+ return {
150
+ "tool": "noop",
151
+ "args": {
152
+ "reason": "invalid_step_type"
153
+ }
154
+ }
155
 
156
+ # =====================================================
157
+ # SAFE TOOL EXECUTION
158
+ # =====================================================
159
+ def _execute_tool(self, action):
160
 
161
+ try:
162
+ if not isinstance(action, dict):
163
+ return {"error": "invalid_action"}
164
 
165
+ if action.get("tool") == "noop":
166
+ return {
167
+ "status": "skipped",
168
+ "reason": action.get("args", {}).get("reason", "unknown")
169
+ }
170
 
171
+ return execute_tool_call(action)
172
 
173
  except Exception as e:
174
+ return {
175
+ "error": str(e)
176
+ }