ehl0wr0ld Rafael Uzarowski commited on
Commit
67b252c
·
unverified ·
1 Parent(s): b7d455f

fix: add missing error handling (#405)

Browse files

Co-authored-by: Rafael Uzarowski <uzarowski.rafael@proton.me>

python/extensions/monologue_end/_50_memorize_fragments.py CHANGED
@@ -45,7 +45,36 @@ class MemorizeMemories(Extension):
45
  background=True,
46
  )
47
 
48
- memories = DirtyJson.parse_string(memories_json)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
 
50
  if not isinstance(memories, list) or len(memories) == 0:
51
  log_item.update(heading="No useful information to memorize.")
 
45
  background=True,
46
  )
47
 
48
+ # Add validation and error handling for memories_json
49
+ if not memories_json or not isinstance(memories_json, str):
50
+ log_item.update(heading="No response from utility model.")
51
+ return
52
+
53
+ # Strip any whitespace that might cause issues
54
+ memories_json = memories_json.strip()
55
+
56
+ if not memories_json:
57
+ log_item.update(heading="Empty response from utility model.")
58
+ return
59
+
60
+ try:
61
+ memories = DirtyJson.parse_string(memories_json)
62
+ except Exception as e:
63
+ log_item.update(heading=f"Failed to parse memories response: {str(e)}")
64
+ return
65
+
66
+ # Validate that memories is a list or convertible to one
67
+ if memories is None:
68
+ log_item.update(heading="No valid memories found in response.")
69
+ return
70
+
71
+ # If memories is not a list, try to make it one
72
+ if not isinstance(memories, list):
73
+ if isinstance(memories, (str, dict)):
74
+ memories = [memories]
75
+ else:
76
+ log_item.update(heading="Invalid memories format received.")
77
+ return
78
 
79
  if not isinstance(memories, list) or len(memories) == 0:
80
  log_item.update(heading="No useful information to memorize.")
python/extensions/monologue_end/_51_memorize_solutions.py CHANGED
@@ -24,8 +24,8 @@ class MemorizeSolutions(Extension):
24
  heading="Memorizing succesful solutions...",
25
  )
26
 
27
- #memorize in background
28
- asyncio.create_task(self.memorize(loop_data, log_item))
29
 
30
  async def memorize(self, loop_data: LoopData, log_item: LogItem, **kwargs):
31
  # get system message and chat history for util llm
@@ -44,7 +44,36 @@ class MemorizeSolutions(Extension):
44
  background=True,
45
  )
46
 
47
- solutions = DirtyJson.parse_string(solutions_json)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
 
49
  if not isinstance(solutions, list) or len(solutions) == 0:
50
  log_item.update(heading="No successful solutions to memorize.")
@@ -61,7 +90,13 @@ class MemorizeSolutions(Extension):
61
  rem = []
62
  for solution in solutions:
63
  # solution to plain text:
64
- txt = f"# Problem\n {solution['problem']}\n# Solution\n {solution['solution']}"
 
 
 
 
 
 
65
  solutions_txt += txt + "\n\n"
66
 
67
  # remove previous solutions too similiar to this one
 
24
  heading="Memorizing succesful solutions...",
25
  )
26
 
27
+ # memorize in background
28
+ asyncio.create_task(self.memorize(loop_data, log_item))
29
 
30
  async def memorize(self, loop_data: LoopData, log_item: LogItem, **kwargs):
31
  # get system message and chat history for util llm
 
44
  background=True,
45
  )
46
 
47
+ # Add validation and error handling for solutions_json
48
+ if not solutions_json or not isinstance(solutions_json, str):
49
+ log_item.update(heading="No response from utility model.")
50
+ return
51
+
52
+ # Strip any whitespace that might cause issues
53
+ solutions_json = solutions_json.strip()
54
+
55
+ if not solutions_json:
56
+ log_item.update(heading="Empty response from utility model.")
57
+ return
58
+
59
+ try:
60
+ solutions = DirtyJson.parse_string(solutions_json)
61
+ except Exception as e:
62
+ log_item.update(heading=f"Failed to parse solutions response: {str(e)}")
63
+ return
64
+
65
+ # Validate that solutions is a list or convertible to one
66
+ if solutions is None:
67
+ log_item.update(heading="No valid solutions found in response.")
68
+ return
69
+
70
+ # If solutions is not a list, try to make it one
71
+ if not isinstance(solutions, list):
72
+ if isinstance(solutions, (str, dict)):
73
+ solutions = [solutions]
74
+ else:
75
+ log_item.update(heading="Invalid solutions format received.")
76
+ return
77
 
78
  if not isinstance(solutions, list) or len(solutions) == 0:
79
  log_item.update(heading="No successful solutions to memorize.")
 
90
  rem = []
91
  for solution in solutions:
92
  # solution to plain text:
93
+ if isinstance(solution, dict):
94
+ problem = solution.get('problem', 'Unknown problem')
95
+ solution_text = solution.get('solution', 'Unknown solution')
96
+ txt = f"# Problem\n {problem}\n# Solution\n {solution_text}"
97
+ else:
98
+ # If solution is not a dict, convert it to string
99
+ txt = f"# Solution\n {str(solution)}"
100
  solutions_txt += txt + "\n\n"
101
 
102
  # remove previous solutions too similiar to this one
python/helpers/dirty_json.py CHANGED
@@ -34,9 +34,19 @@ class DirtyJson:
34
  def parse(self, json_string):
35
  self._reset()
36
  self.json_string = json_string
37
- self.index = self.get_start_pos(
38
- self.json_string
39
- ) # skip any text up to the first brace
 
 
 
 
 
 
 
 
 
 
40
  self.current_char = self.json_string[self.index]
41
  self._parse()
42
  return self.result
 
34
  def parse(self, json_string):
35
  self._reset()
36
  self.json_string = json_string
37
+
38
+ # Add bounds checking to prevent IndexError
39
+ if not json_string:
40
+ # Return None for empty strings
41
+ return None
42
+
43
+ self.index = self.get_start_pos(self.json_string)
44
+
45
+ # Ensure index is within bounds
46
+ if self.index >= len(self.json_string):
47
+ # If start position is beyond string length, return None
48
+ return None
49
+
50
  self.current_char = self.json_string[self.index]
51
  self._parse()
52
  return self.result
python/helpers/extract_tools.py CHANGED
@@ -6,10 +6,17 @@ import regex
6
  from fnmatch import fnmatch
7
 
8
  def json_parse_dirty(json:str) -> dict[str,Any] | None:
9
- ext_json = extract_json_object_string(json)
 
 
 
10
  if ext_json:
11
- data = DirtyJson.parse_string(ext_json)
12
- if isinstance(data,dict): return data
 
 
 
 
13
  return None
14
 
15
  def extract_json_object_string(content):
@@ -29,10 +36,10 @@ def extract_json_object_string(content):
29
  def extract_json_string(content):
30
  # Regular expression pattern to match a JSON object
31
  pattern = r'\{(?:[^{}]|(?R))*\}|\[(?:[^\[\]]|(?R))*\]|"(?:\\.|[^"\\])*"|true|false|null|-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?'
32
-
33
  # Search for the pattern in the content
34
  match = regex.search(pattern, content)
35
-
36
  if match:
37
  # Return the matched JSON string
38
  return match.group(0)
@@ -77,4 +84,4 @@ def load_classes_from_folder(folder: str, name_pattern: str, base_class: Type[T]
77
  if one_per_file:
78
  break
79
 
80
- return classes
 
6
  from fnmatch import fnmatch
7
 
8
  def json_parse_dirty(json:str) -> dict[str,Any] | None:
9
+ if not json or not isinstance(json, str):
10
+ return None
11
+
12
+ ext_json = extract_json_object_string(json.strip())
13
  if ext_json:
14
+ try:
15
+ data = DirtyJson.parse_string(ext_json)
16
+ if isinstance(data,dict): return data
17
+ except Exception:
18
+ # If parsing fails, return None instead of crashing
19
+ return None
20
  return None
21
 
22
  def extract_json_object_string(content):
 
36
  def extract_json_string(content):
37
  # Regular expression pattern to match a JSON object
38
  pattern = r'\{(?:[^{}]|(?R))*\}|\[(?:[^\[\]]|(?R))*\]|"(?:\\.|[^"\\])*"|true|false|null|-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?'
39
+
40
  # Search for the pattern in the content
41
  match = regex.search(pattern, content)
42
+
43
  if match:
44
  # Return the matched JSON string
45
  return match.group(0)
 
84
  if one_per_file:
85
  break
86
 
87
+ return classes
python/tools/browser_agent.py CHANGED
@@ -5,7 +5,7 @@ from agent import Agent, InterventionException
5
 
6
  import models
7
  from python.helpers.tool import Tool, Response
8
- from python.helpers import files, defer, persist_chat
9
  from python.helpers.browser_use import browser_use
10
  from python.extensions.message_loop_start._10_iteration_no import get_iter_no
11
  from pydantic import BaseModel
@@ -184,10 +184,13 @@ class BrowserAgent(Tool):
184
  result = await task.result()
185
  answer = result.final_result()
186
  try:
187
- answer_data = DirtyJson.parse_string(answer)
188
- answer_text = strings.dict_to_text(answer_data) # type: ignore
 
 
 
189
  except Exception as e:
190
- answer_text = answer
191
  self.log.update(answer=answer_text)
192
  return Response(message=answer, break_loop=False)
193
 
 
5
 
6
  import models
7
  from python.helpers.tool import Tool, Response
8
+ from python.helpers import files, defer, persist_chat, strings
9
  from python.helpers.browser_use import browser_use
10
  from python.extensions.message_loop_start._10_iteration_no import get_iter_no
11
  from pydantic import BaseModel
 
184
  result = await task.result()
185
  answer = result.final_result()
186
  try:
187
+ if answer and isinstance(answer, str) and answer.strip():
188
+ answer_data = DirtyJson.parse_string(answer)
189
+ answer_text = strings.dict_to_text(answer_data) # type: ignore
190
+ else:
191
+ answer_text = str(answer) if answer else "No result returned"
192
  except Exception as e:
193
+ answer_text = str(answer) if answer else f"Error processing result: {str(e)}"
194
  self.log.update(answer=answer_text)
195
  return Response(message=answer, break_loop=False)
196