PYAE1994 commited on
Commit
0ceac21
·
verified ·
1 Parent(s): e36ea50

Update app/agent/agent.py

Browse files
Files changed (1) hide show
  1. app/agent/agent.py +84 -108
app/agent/agent.py CHANGED
@@ -7,95 +7,88 @@ from executor import Executor
7
  from tools_runtime import execute_tool_call
8
 
9
 
10
- class Agent:
 
 
 
11
 
12
  def __init__(self):
13
- self.history = []
14
- self.executor = Executor(llm=self.call_llm)
 
 
 
 
 
15
 
16
- # =====================================================
17
- # SAFE LLM CALL LAYER (HARDENED)
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={
28
- "Authorization": f"Bearer {Config.LLM_API_KEY}",
29
- "Content-Type": "application/json"
30
- },
31
- json={
32
- "model": Config.MODEL,
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 (ALWAYS SAFE OUTPUT)
63
- # =====================================================
64
- def _fallback(self, error):
65
  return {
66
- "error": error,
67
- "choices": [
68
- {
69
- "message": {
70
- "content": "LLM_ERROR"
71
- }
72
  }
73
- ]
 
74
  }
75
 
76
- # =====================================================
77
- # SAFE CONTENT EXTRACTION
78
- # =====================================================
79
- def _extract_content(self, response):
80
 
81
- try:
82
- if not isinstance(response, dict):
83
- return ""
 
84
 
85
- return (
86
- response.get("choices", [{}])[0]
87
- .get("message", {})
88
- .get("content", "")
89
- )
90
- except Exception:
91
- return ""
92
 
93
  # =====================================================
94
- # GOAL MODE (SAFE PIPELINE)
95
  # =====================================================
96
  def run_goal(self, goal: str):
97
 
98
- # PLAN PHASE
99
  try:
100
  plan = create_plan(goal)
101
 
@@ -108,11 +101,10 @@ class Agent:
108
  "error": f"plan_failed: {str(e)}"
109
  }
110
 
111
- # EXECUTION PHASE
112
  try:
113
  results = self.executor.run_plan(plan)
114
  except Exception as e:
115
- results = {"error": f"executor_failed: {str(e)}"}
116
 
117
  return {
118
  "mode": "goal_execution",
@@ -129,25 +121,7 @@ class Agent:
129
  messages = [
130
  {
131
  "role": "system",
132
- "content": Config.SYSTEM_PROMPT + """
133
-
134
- You are a strict autonomous coding agent.
135
-
136
- RULES:
137
- - TOOL MODE → ONLY valid JSON
138
- - NORMAL MODE → plain text only
139
-
140
- TOOLS:
141
- run_shell(cmd)
142
- write_file(path, content)
143
- read_file(path)
144
- list_files(path)
145
- delete_file(path)
146
- browser_open(url)
147
- browser_click(selector)
148
- browser_type(selector, text)
149
- browser_screenshot(path)
150
- """
151
  },
152
  {
153
  "role": "user",
@@ -155,8 +129,19 @@ browser_screenshot(path)
155
  }
156
  ]
157
 
158
- response = self.call_llm(messages)
159
- content = self._extract_content(response)
 
 
 
 
 
 
 
 
 
 
 
160
 
161
  if not content:
162
  return {
@@ -164,29 +149,19 @@ browser_screenshot(path)
164
  "response": "empty_llm_response"
165
  }
166
 
167
- # =================================================
168
- # TOOL EXECUTION PATH (SAFE JSON PARSE)
169
- # =================================================
170
  try:
171
- tool_call = json.loads(content)
172
 
173
- if isinstance(tool_call, dict) and "tool" in tool_call:
174
 
175
- result = execute_tool_call(tool_call)
176
-
177
- # SAFE HEALER (NO CRASH)
178
- try:
179
- fix = self.executor.healer.heal(user_input, result)
180
-
181
- if isinstance(fix, dict) and "tool" in fix:
182
- result = execute_tool_call(fix)
183
-
184
- except Exception:
185
- pass
186
 
187
  self.history.append({
188
  "input": user_input,
189
- "tool_call": tool_call,
190
  "result": result
191
  })
192
 
@@ -198,9 +173,9 @@ browser_screenshot(path)
198
  except Exception:
199
  pass
200
 
201
- # =================================================
202
- # NORMAL RESPONSE
203
- # =================================================
204
  return {
205
  "mode": "normal_response",
206
  "response": content
@@ -211,6 +186,7 @@ browser_screenshot(path)
211
  # DEBUG
212
  # =====================================================
213
  if __name__ == "__main__":
 
214
  agent = Agent()
215
 
216
  print(agent.run("List files in current directory"))
 
7
  from tools_runtime import execute_tool_call
8
 
9
 
10
+ # =====================================================
11
+ # 🔥 UNIVERSAL LLM ROUTER (INSIDE agent.py)
12
+ # =====================================================
13
+ class LLMRouter:
14
 
15
  def __init__(self):
16
+ self.providers = [
17
+ {
18
+ "url": Config.LLM_API_URL,
19
+ "key": Config.LLM_API_KEY,
20
+ "model": Config.MODEL
21
+ }
22
+ ]
23
 
24
+ def call(self, messages):
 
 
 
25
 
26
+ last_error = None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
 
28
+ for p in self.providers:
 
 
29
 
 
30
  try:
31
+ res = requests.post(
32
+ p["url"],
33
+ headers={
34
+ "Authorization": f"Bearer {p['key']}",
35
+ "Content-Type": "application/json"
36
+ },
37
+ json={
38
+ "model": p["model"],
39
+ "messages": messages,
40
+ "temperature": 0.2
41
+ },
42
+ timeout=30
43
+ )
44
+
45
  data = res.json()
 
 
46
 
47
+ # =========================
48
+ # NORMALIZER (IMPORTANT FIX)
49
+ # =========================
50
+ if isinstance(data, list):
51
+ data = data[0] if data else {}
52
 
53
+ if isinstance(data, dict) and "result" in data:
54
+ data = data["result"]
55
 
56
+ # =========================
57
+ # VALIDATION
58
+ # =========================
59
+ if isinstance(data, dict) and "choices" in data:
60
+ return data
61
 
62
+ except Exception as e:
63
+ last_error = str(e)
64
+ continue
65
 
 
 
 
 
66
  return {
67
+ "choices": [{
68
+ "message": {
69
+ "content": "LLM_ERROR"
 
 
 
70
  }
71
+ }],
72
+ "error": last_error
73
  }
74
 
 
 
 
 
75
 
76
+ # =====================================================
77
+ # AGENT
78
+ # =====================================================
79
+ class Agent:
80
 
81
+ def __init__(self):
82
+
83
+ self.llm = LLMRouter().call
84
+ self.executor = Executor(llm=self.llm)
85
+ self.history = []
 
 
86
 
87
  # =====================================================
88
+ # GOAL MODE
89
  # =====================================================
90
  def run_goal(self, goal: str):
91
 
 
92
  try:
93
  plan = create_plan(goal)
94
 
 
101
  "error": f"plan_failed: {str(e)}"
102
  }
103
 
 
104
  try:
105
  results = self.executor.run_plan(plan)
106
  except Exception as e:
107
+ results = {"error": str(e)}
108
 
109
  return {
110
  "mode": "goal_execution",
 
121
  messages = [
122
  {
123
  "role": "system",
124
+ "content": Config.SYSTEM_PROMPT
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125
  },
126
  {
127
  "role": "user",
 
129
  }
130
  ]
131
 
132
+ response = self.llm(messages)
133
+
134
+ # =========================
135
+ # SAFE EXTRACTION
136
+ # =========================
137
+ try:
138
+ content = (
139
+ response.get("choices", [{}])[0]
140
+ .get("message", {})
141
+ .get("content", "")
142
+ )
143
+ except Exception:
144
+ content = ""
145
 
146
  if not content:
147
  return {
 
149
  "response": "empty_llm_response"
150
  }
151
 
152
+ # =========================
153
+ # TOOL MODE
154
+ # =========================
155
  try:
156
+ tool = json.loads(content)
157
 
158
+ if isinstance(tool, dict) and "tool" in tool:
159
 
160
+ result = execute_tool_call(tool)
 
 
 
 
 
 
 
 
 
 
161
 
162
  self.history.append({
163
  "input": user_input,
164
+ "tool_call": tool,
165
  "result": result
166
  })
167
 
 
173
  except Exception:
174
  pass
175
 
176
+ # =========================
177
+ # NORMAL MODE
178
+ # =========================
179
  return {
180
  "mode": "normal_response",
181
  "response": content
 
186
  # DEBUG
187
  # =====================================================
188
  if __name__ == "__main__":
189
+
190
  agent = Agent()
191
 
192
  print(agent.run("List files in current directory"))