Commit
·
fde43e7
1
Parent(s):
0e58feb
Fixing tool deletion
Browse files
src/manager/agent_manager.py
CHANGED
@@ -12,6 +12,9 @@ import os
|
|
12 |
from dotenv import load_dotenv
|
13 |
from src.manager.budget_manager import BudgetManager
|
14 |
|
|
|
|
|
|
|
15 |
class Agent(ABC):
|
16 |
|
17 |
def __init__(self, agent_name: str, base_model: str, system_prompt: str, creation_cost: str, invoke_cost: str):
|
@@ -105,7 +108,10 @@ class AgentManager():
|
|
105 |
|
106 |
self._load_agents()
|
107 |
|
108 |
-
def create_agent(self, agent_name: str,
|
|
|
|
|
|
|
109 |
**additional_params) -> Tuple[Agent, int]:
|
110 |
|
111 |
if agent_name in self._agents:
|
@@ -163,8 +169,8 @@ class AgentManager():
|
|
163 |
def list_agents(self) -> dict:
|
164 |
"""Return agent information (name, description, costs)"""
|
165 |
try:
|
166 |
-
if os.path.exists(
|
167 |
-
with open(
|
168 |
full_models = json.loads(f.read())
|
169 |
|
170 |
# Create a simplified version with only the description and costs
|
@@ -191,12 +197,12 @@ class AgentManager():
|
|
191 |
|
192 |
del self._agents[agent_name]
|
193 |
try:
|
194 |
-
if os.path.exists(
|
195 |
-
with open(
|
196 |
models = json.loads(f.read())
|
197 |
|
198 |
del models[agent_name]
|
199 |
-
with open(
|
200 |
f.write(json.dumps(models, indent=4))
|
201 |
except Exception as e:
|
202 |
output_assistant_response(f"Error deleting agent: {e}")
|
@@ -216,11 +222,11 @@ class AgentManager():
|
|
216 |
"""Save a single agent to the models.json file"""
|
217 |
try:
|
218 |
# Ensure the directory exists
|
219 |
-
os.makedirs(
|
220 |
|
221 |
# Read existing models file or create empty dict if it doesn't exist
|
222 |
try:
|
223 |
-
with open(
|
224 |
models = json.loads(f.read())
|
225 |
except (FileNotFoundError, json.JSONDecodeError):
|
226 |
models = {}
|
@@ -239,7 +245,7 @@ class AgentManager():
|
|
239 |
models[agent_name][key] = value
|
240 |
|
241 |
# Write the updated models back to the file
|
242 |
-
with open(
|
243 |
f.write(json.dumps(models, indent=4))
|
244 |
|
245 |
except Exception as e:
|
@@ -259,10 +265,10 @@ class AgentManager():
|
|
259 |
def _load_agents(self) -> None:
|
260 |
"""Load agent configurations from disk"""
|
261 |
try:
|
262 |
-
if not os.path.exists(
|
263 |
return
|
264 |
|
265 |
-
with open(
|
266 |
models = json.loads(f.read())
|
267 |
|
268 |
for name, data in models.items():
|
|
|
12 |
from dotenv import load_dotenv
|
13 |
from src.manager.budget_manager import BudgetManager
|
14 |
|
15 |
+
MODEL_PATH = "./src/models/"
|
16 |
+
MODEL_FILE_PATH = "./src/models/models.json"
|
17 |
+
|
18 |
class Agent(ABC):
|
19 |
|
20 |
def __init__(self, agent_name: str, base_model: str, system_prompt: str, creation_cost: str, invoke_cost: str):
|
|
|
108 |
|
109 |
self._load_agents()
|
110 |
|
111 |
+
def create_agent(self, agent_name: str,
|
112 |
+
base_model: str, system_prompt: str,
|
113 |
+
description: str = "", create_cost: float = 0,
|
114 |
+
invoke_cost: float = 0,
|
115 |
**additional_params) -> Tuple[Agent, int]:
|
116 |
|
117 |
if agent_name in self._agents:
|
|
|
169 |
def list_agents(self) -> dict:
|
170 |
"""Return agent information (name, description, costs)"""
|
171 |
try:
|
172 |
+
if os.path.exists(MODEL_FILE_PATH):
|
173 |
+
with open(MODEL_FILE_PATH, "r", encoding="utf8") as f:
|
174 |
full_models = json.loads(f.read())
|
175 |
|
176 |
# Create a simplified version with only the description and costs
|
|
|
197 |
|
198 |
del self._agents[agent_name]
|
199 |
try:
|
200 |
+
if os.path.exists(MODEL_FILE_PATH):
|
201 |
+
with open(MODEL_FILE_PATH, "r", encoding="utf8") as f:
|
202 |
models = json.loads(f.read())
|
203 |
|
204 |
del models[agent_name]
|
205 |
+
with open(MODEL_FILE_PATH, "w", encoding="utf8") as f:
|
206 |
f.write(json.dumps(models, indent=4))
|
207 |
except Exception as e:
|
208 |
output_assistant_response(f"Error deleting agent: {e}")
|
|
|
222 |
"""Save a single agent to the models.json file"""
|
223 |
try:
|
224 |
# Ensure the directory exists
|
225 |
+
os.makedirs(MODEL_PATH, exist_ok=True)
|
226 |
|
227 |
# Read existing models file or create empty dict if it doesn't exist
|
228 |
try:
|
229 |
+
with open(MODEL_FILE_PATH, "r", encoding="utf8") as f:
|
230 |
models = json.loads(f.read())
|
231 |
except (FileNotFoundError, json.JSONDecodeError):
|
232 |
models = {}
|
|
|
245 |
models[agent_name][key] = value
|
246 |
|
247 |
# Write the updated models back to the file
|
248 |
+
with open(MODEL_FILE_PATH, "w", encoding="utf8") as f:
|
249 |
f.write(json.dumps(models, indent=4))
|
250 |
|
251 |
except Exception as e:
|
|
|
265 |
def _load_agents(self) -> None:
|
266 |
"""Load agent configurations from disk"""
|
267 |
try:
|
268 |
+
if not os.path.exists(MODEL_FILE_PATH):
|
269 |
return
|
270 |
|
271 |
+
with open(MODEL_FILE_PATH, "r", encoding="utf8") as f:
|
272 |
models = json.loads(f.read())
|
273 |
|
274 |
for name, data in models.items():
|
src/manager/manager.py
CHANGED
@@ -98,14 +98,11 @@ class GeminiManager:
|
|
98 |
self.toolsLoader.load_tools()
|
99 |
except Exception as e:
|
100 |
logger.info(f"Error loading tools: {e}. Deleting the tool.")
|
101 |
-
thinking += f"Error loading tools: {e}. Deleting the tool.\n"
|
102 |
yield {
|
103 |
"role": "assistant",
|
104 |
-
"content":
|
105 |
"metadata": {
|
106 |
-
"title":
|
107 |
-
"id": i,
|
108 |
-
"status": "done",
|
109 |
}
|
110 |
}
|
111 |
# delete the created tool
|
|
|
98 |
self.toolsLoader.load_tools()
|
99 |
except Exception as e:
|
100 |
logger.info(f"Error loading tools: {e}. Deleting the tool.")
|
|
|
101 |
yield {
|
102 |
"role": "assistant",
|
103 |
+
"content": f"Error loading tools: {e}. Deleting the tool.\n",
|
104 |
"metadata": {
|
105 |
+
"title": "Trying to load the newly created tool",
|
|
|
|
|
106 |
}
|
107 |
}
|
108 |
# delete the created tool
|
src/models/models.json
CHANGED
@@ -1 +1,16 @@
|
|
1 |
-
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"RecipeAgent": {
|
3 |
+
"base_model": "gemini-2.5-flash-preview-04-17",
|
4 |
+
"description": "Agent that extracts recipe from a website",
|
5 |
+
"system_prompt": "You are a recipe extraction agent. Given a URL, you extract the title, ingredients, and instructions from the website. If you cannot find the recipe, you return an error message.",
|
6 |
+
"create_cost": 20,
|
7 |
+
"invoke_cost": 50
|
8 |
+
},
|
9 |
+
"TimeAgent": {
|
10 |
+
"base_model": "gemini-2.0-flash",
|
11 |
+
"description": "An agent that provides the current time.",
|
12 |
+
"system_prompt": "You are a helpful agent that provides the current time in the format YYYY-MM-DD HH:MM:SS. Use the current date and time to respond to the user. Do not use any external tools or APIs.",
|
13 |
+
"create_cost": 20,
|
14 |
+
"invoke_cost": 50
|
15 |
+
}
|
16 |
+
}
|
src/models/system3.prompt
CHANGED
@@ -34,7 +34,7 @@ If you're over this budget, you can no longer create new tools. In case this hap
|
|
34 |
</Info>
|
35 |
|
36 |
<Info>
|
37 |
-
|
38 |
</Info>
|
39 |
|
40 |
Here's a set of rules you must follow:
|
@@ -123,5 +123,9 @@ When you go over the resource budget, you must carefully evaluate which agent is
|
|
123 |
</Rule>
|
124 |
|
125 |
<Rule>
|
126 |
-
|
|
|
|
|
|
|
|
|
127 |
</Rule>
|
|
|
34 |
</Info>
|
35 |
|
36 |
<Info>
|
37 |
+
If user shares something important or sensitive, you should usee the UpdateMemory tool to store this information. Include details such as the user's preferences, how you solved errors, and any other relevant context that could help in future interactions. This will help you provide better assistance in the future.
|
38 |
</Info>
|
39 |
|
40 |
Here's a set of rules you must follow:
|
|
|
123 |
</Rule>
|
124 |
|
125 |
<Rule>
|
126 |
+
Every time you encounter an error and fix it, you should use the UpdateMemory tool to store the FIX.
|
127 |
+
</Rule>
|
128 |
+
|
129 |
+
<Rule>
|
130 |
+
Every time user corrects you or provides feedback, you should use the UpdateMemory tool to store this information.
|
131 |
</Rule>
|
src/tools/default_tools/tool_creator.py
CHANGED
@@ -23,6 +23,15 @@ class ToolCreator():
|
|
23 |
"required": ["name", "tool_code"],
|
24 |
}
|
25 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
26 |
|
27 |
def run(self, **kwargs):
|
28 |
print("Running Tool Creator")
|
@@ -31,7 +40,7 @@ class ToolCreator():
|
|
31 |
print(f"Tool Name: {name}")
|
32 |
print(f"Tool Content: {content}")
|
33 |
# Create the tool file
|
34 |
-
tool_file_path = f"tools/{name}.py"
|
35 |
with open(tool_file_path, "w") as tool_file:
|
36 |
tool_file.write(content)
|
37 |
print(f"Tool file created at {tool_file_path}")
|
|
|
23 |
"required": ["name", "tool_code"],
|
24 |
}
|
25 |
}
|
26 |
+
|
27 |
+
def validate_tool_code(self, tool_code):
|
28 |
+
# Basic validation to check if the code is a valid Python function
|
29 |
+
try:
|
30 |
+
compile(tool_code, '<string>', 'exec')
|
31 |
+
return True, None
|
32 |
+
except SyntaxError as e:
|
33 |
+
print(f"Syntax error in tool code: {e}")
|
34 |
+
return False, e
|
35 |
|
36 |
def run(self, **kwargs):
|
37 |
print("Running Tool Creator")
|
|
|
40 |
print(f"Tool Name: {name}")
|
41 |
print(f"Tool Content: {content}")
|
42 |
# Create the tool file
|
43 |
+
tool_file_path = f"src/tools/user_tools/{name}.py"
|
44 |
with open(tool_file_path, "w") as tool_file:
|
45 |
tool_file.write(content)
|
46 |
print(f"Tool file created at {tool_file_path}")
|
src/tools/default_tools/tool_deletor.py
CHANGED
@@ -30,7 +30,7 @@ class ToolDeletor():
|
|
30 |
name = kwargs.get("name")
|
31 |
file_path = kwargs.get("file_path")
|
32 |
# make sure the file path is in tools/
|
33 |
-
if not file_path.startswith("tools/"):
|
34 |
return {
|
35 |
"status": "error",
|
36 |
"message": "File path must start with tools/",
|
|
|
30 |
name = kwargs.get("name")
|
31 |
file_path = kwargs.get("file_path")
|
32 |
# make sure the file path is in tools/
|
33 |
+
if not file_path.startswith("src/tools/user_tools/"):
|
34 |
return {
|
35 |
"status": "error",
|
36 |
"message": "File path must start with tools/",
|
src/tools/default_tools/update_memory.py
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
|
2 |
__all__ = ['UpdateMemory']
|
3 |
|
4 |
-
|
5 |
|
6 |
|
7 |
class UpdateMemory():
|
@@ -24,9 +24,32 @@ class UpdateMemory():
|
|
24 |
|
25 |
|
26 |
def run(self, **kwargs):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
return {
|
28 |
-
"status": "
|
29 |
-
"message": "
|
30 |
-
"output":
|
31 |
-
}
|
32 |
-
|
|
|
1 |
|
2 |
__all__ = ['UpdateMemory']
|
3 |
|
4 |
+
import json
|
5 |
|
6 |
|
7 |
class UpdateMemory():
|
|
|
24 |
|
25 |
|
26 |
def run(self, **kwargs):
|
27 |
+
# save it to src/data/memory.json
|
28 |
+
memory = kwargs.get("memory")
|
29 |
+
if not memory:
|
30 |
+
return {
|
31 |
+
"status": "error",
|
32 |
+
"message": "Memory is required",
|
33 |
+
"output": None
|
34 |
+
}
|
35 |
+
# add the memory to the memory.json file which is list of strings
|
36 |
+
# create the file if it does not exist
|
37 |
+
try:
|
38 |
+
with open("src/data/memory.json", "r") as f:
|
39 |
+
memory_list = json.load(f)
|
40 |
+
except FileNotFoundError:
|
41 |
+
memory_list = []
|
42 |
+
except json.JSONDecodeError:
|
43 |
+
memory_list = []
|
44 |
+
|
45 |
+
# add the new memory to the list
|
46 |
+
memory_list.append(memory)
|
47 |
+
# save the list to the file
|
48 |
+
with open("src/data/memory.json", "w") as f:
|
49 |
+
json.dump(memory_list, f)
|
50 |
+
# return the list of memories
|
51 |
return {
|
52 |
+
"status": "success",
|
53 |
+
"message": "Memory updated successfully",
|
54 |
+
"output": memory_list
|
55 |
+
}
|
|