PYAE1994 commited on
Commit
e1bd82f
·
verified ·
1 Parent(s): 79b1d3b

Update app/agent/agent.py

Browse files
Files changed (1) hide show
  1. app/agent/agent.py +58 -48
app/agent/agent.py CHANGED
@@ -14,11 +14,14 @@ class Agent:
14
  self.executor = Executor(llm=self.call_llm)
15
 
16
  # =====================================================
17
- # LLM CALL LAYER (ROBUST)
18
  # =====================================================
19
  def call_llm(self, messages):
20
 
21
  try:
 
 
 
22
  res = requests.post(
23
  Config.LLM_API_URL,
24
  headers={
@@ -30,33 +33,37 @@ class Agent:
30
  "messages": messages,
31
  "temperature": 0.2
32
  },
33
- timeout=60
34
  )
35
 
36
  # HTTP check
37
- res.raise_for_status()
 
38
 
39
- data = res.json()
 
 
 
 
40
 
41
  # structure validation
42
  if not isinstance(data, dict):
43
- return self._llm_fallback("invalid_response")
44
 
45
  if "choices" not in data:
46
- return self._llm_fallback("missing_choices")
47
 
48
  return data
49
 
50
  except Exception as e:
51
- return self._llm_fallback(str(e))
52
 
53
  # =====================================================
54
- # SAFE FALLBACK RESPONSE
55
  # =====================================================
56
- def _llm_fallback(self, error_msg):
57
-
58
  return {
59
- "error": error_msg,
60
  "choices": [
61
  {
62
  "message": {
@@ -67,19 +74,39 @@ class Agent:
67
  }
68
 
69
  # =====================================================
70
- # GOAL MODE (AUTONOMOUS)
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  # =====================================================
72
  def run_goal(self, goal: str):
73
 
74
  try:
75
  plan = create_plan(goal)
 
 
 
 
76
  except Exception as e:
77
  return {
78
  "mode": "error",
79
  "error": f"plan_failed: {str(e)}"
80
  }
81
 
82
- results = self.executor.run_plan(plan)
 
 
 
83
 
84
  return {
85
  "mode": "goal_execution",
@@ -98,26 +125,22 @@ class Agent:
98
  "role": "system",
99
  "content": Config.SYSTEM_PROMPT + """
100
 
101
- You are an autonomous coding + browser + planning agent.
102
 
103
- MODES:
104
- - TOOL MODE → STRICT JSON ONLY
105
- - NORMAL MODE → plain text
106
 
107
  TOOLS:
108
- - run_shell(cmd)
109
- - write_file(path, content)
110
- - read_file(path)
111
- - list_files(path)
112
- - delete_file(path)
113
- - browser_open(url)
114
- - browser_click(selector)
115
- - browser_type(selector, text)
116
- - browser_screenshot(path)
117
-
118
- RULE:
119
- If action → JSON ONLY
120
- If explanation → text only
121
  """
122
  },
123
  {
@@ -127,27 +150,16 @@ If explanation → text only
127
  ]
128
 
129
  response = self.call_llm(messages)
130
-
131
- # =================================================
132
- # SAFE CONTENT EXTRACTION
133
- # =================================================
134
- content = None
135
-
136
- try:
137
- content = response.get("choices", [{}])[0] \
138
- .get("message", {}) \
139
- .get("content", None)
140
- except Exception:
141
- content = None
142
 
143
  if not content:
144
  return {
145
  "mode": "error",
146
- "response": "Empty LLM response"
147
  }
148
 
149
  # =================================================
150
- # TOOL EXECUTION PATH
151
  # =================================================
152
  try:
153
  tool_call = json.loads(content)
@@ -156,13 +168,11 @@ If explanation → text only
156
 
157
  result = execute_tool_call(tool_call)
158
 
159
- # SAFE HEALER CALL (NO CRASH)
160
  try:
161
  fix = self.executor.healer.heal(user_input, result)
162
-
163
  if isinstance(fix, dict) and "tool" in fix:
164
  result = execute_tool_call(fix)
165
-
166
  except Exception:
167
  pass
168
 
@@ -177,7 +187,7 @@ If explanation → text only
177
  "result": result
178
  }
179
 
180
- except json.JSONDecodeError:
181
  pass
182
 
183
  # =================================================
 
14
  self.executor = Executor(llm=self.call_llm)
15
 
16
  # =====================================================
17
+ # SAFE LLM CALL LAYER (NO CRASH GUARANTEE)
18
  # =====================================================
19
  def call_llm(self, messages):
20
 
21
  try:
22
+ if not Config.LLM_API_URL:
23
+ return self._fallback("missing_llm_url")
24
+
25
  res = requests.post(
26
  Config.LLM_API_URL,
27
  headers={
 
33
  "messages": messages,
34
  "temperature": 0.2
35
  },
36
+ timeout=30
37
  )
38
 
39
  # HTTP check
40
+ if res.status_code != 200:
41
+ return self._fallback(f"http_{res.status_code}")
42
 
43
+ # JSON parse safe
44
+ try:
45
+ data = res.json()
46
+ except Exception:
47
+ return self._fallback("invalid_json")
48
 
49
  # structure validation
50
  if not isinstance(data, dict):
51
+ return self._fallback("invalid_structure")
52
 
53
  if "choices" not in data:
54
+ return self._fallback("missing_choices")
55
 
56
  return data
57
 
58
  except Exception as e:
59
+ return self._fallback(str(e))
60
 
61
  # =====================================================
62
+ # FALLBACK RESPONSE (ALWAYS SAFE)
63
  # =====================================================
64
+ def _fallback(self, error):
 
65
  return {
66
+ "error": error,
67
  "choices": [
68
  {
69
  "message": {
 
74
  }
75
 
76
  # =====================================================
77
+ # SAFE CONTENT EXTRACTION
78
+ # =====================================================
79
+ def _extract_content(self, response):
80
+ try:
81
+ return (
82
+ response.get("choices", [{}])[0]
83
+ .get("message", {})
84
+ .get("content", "")
85
+ )
86
+ except Exception:
87
+ return ""
88
+
89
+ # =====================================================
90
+ # GOAL MODE (AUTONOMOUS SAFE)
91
  # =====================================================
92
  def run_goal(self, goal: str):
93
 
94
  try:
95
  plan = create_plan(goal)
96
+
97
+ if not isinstance(plan, dict):
98
+ return {"mode": "error", "error": "invalid_plan"}
99
+
100
  except Exception as e:
101
  return {
102
  "mode": "error",
103
  "error": f"plan_failed: {str(e)}"
104
  }
105
 
106
+ try:
107
+ results = self.executor.run_plan(plan)
108
+ except Exception as e:
109
+ results = {"error": f"executor_failed: {str(e)}"}
110
 
111
  return {
112
  "mode": "goal_execution",
 
125
  "role": "system",
126
  "content": Config.SYSTEM_PROMPT + """
127
 
128
+ You are an autonomous coding + tool execution agent.
129
 
130
+ OUTPUT RULES:
131
+ - TOOL MODE → strict JSON only
132
+ - NORMAL MODE → plain text only
133
 
134
  TOOLS:
135
+ run_shell(cmd)
136
+ write_file(path, content)
137
+ read_file(path)
138
+ list_files(path)
139
+ delete_file(path)
140
+ browser_open(url)
141
+ browser_click(selector)
142
+ browser_type(selector, text)
143
+ browser_screenshot(path)
 
 
 
 
144
  """
145
  },
146
  {
 
150
  ]
151
 
152
  response = self.call_llm(messages)
153
+ content = self._extract_content(response)
 
 
 
 
 
 
 
 
 
 
 
154
 
155
  if not content:
156
  return {
157
  "mode": "error",
158
+ "response": "empty_llm_response"
159
  }
160
 
161
  # =================================================
162
+ # TOOL MODE SAFE PARSE
163
  # =================================================
164
  try:
165
  tool_call = json.loads(content)
 
168
 
169
  result = execute_tool_call(tool_call)
170
 
171
+ # optional healer (NO CRASH GUARANTEE)
172
  try:
173
  fix = self.executor.healer.heal(user_input, result)
 
174
  if isinstance(fix, dict) and "tool" in fix:
175
  result = execute_tool_call(fix)
 
176
  except Exception:
177
  pass
178
 
 
187
  "result": result
188
  }
189
 
190
+ except Exception:
191
  pass
192
 
193
  # =================================================