Spaces:
Sleeping
Sleeping
Commit ·
149a97d
1
Parent(s): 21ca484
Injecting tool param usage - InjectedState
Browse files
agents/jarvis_mcp_memory_agent.py
CHANGED
|
@@ -17,6 +17,7 @@ from tools.tools_registry import local_tools
|
|
| 17 |
|
| 18 |
class State(TypedDict):
|
| 19 |
messages: Annotated[list, add_messages]
|
|
|
|
| 20 |
|
| 21 |
server_config_path = "mcp\server_config.json"
|
| 22 |
|
|
|
|
| 17 |
|
| 18 |
class State(TypedDict):
|
| 19 |
messages: Annotated[list, add_messages]
|
| 20 |
+
real_name: str # Added to pass real_name to tools
|
| 21 |
|
| 22 |
server_config_path = "mcp\server_config.json"
|
| 23 |
|
agents/jarvis_memory_agent.py
CHANGED
|
@@ -10,6 +10,7 @@ from tools.tools_registry import local_tools
|
|
| 10 |
|
| 11 |
class State(TypedDict):
|
| 12 |
messages: Annotated[list, add_messages]
|
|
|
|
| 13 |
|
| 14 |
class JarvisMemoryAgent:
|
| 15 |
def __init__(self, model_enum: ModelEnum):
|
|
|
|
| 10 |
|
| 11 |
class State(TypedDict):
|
| 12 |
messages: Annotated[list, add_messages]
|
| 13 |
+
real_name: str # Added to pass real_name to tools
|
| 14 |
|
| 15 |
class JarvisMemoryAgent:
|
| 16 |
def __init__(self, model_enum: ModelEnum):
|
agents/session.py
CHANGED
|
@@ -14,6 +14,8 @@ class ChatState(Enum):
|
|
| 14 |
STARTING_CHAT = "STARTING_CHAT"
|
| 15 |
INITIALIZED = "INITIALIZED"
|
| 16 |
|
|
|
|
|
|
|
| 17 |
|
| 18 |
# === Global caches ===
|
| 19 |
_sessions_cache: dict[tuple[ModelEnum, str], "JarvisSession"] = {}
|
|
@@ -110,7 +112,7 @@ class JarvisSession:
|
|
| 110 |
return {"role": role, "content": content}
|
| 111 |
|
| 112 |
def _build_agent_kwargs(self, messages: list) -> dict:
|
| 113 |
-
kwargs = {"input": {"messages": messages}}
|
| 114 |
if self.model_enum in models_with_memory:
|
| 115 |
kwargs["config"] = {"configurable": {"thread_id": self.thread_id}}
|
| 116 |
return kwargs
|
|
@@ -134,7 +136,8 @@ class JarvisSession:
|
|
| 134 |
for tool_call in msg.additional_kwargs['tool_calls']:
|
| 135 |
result.append(f"Llamando a la función: {tool_call['function']['name']}")
|
| 136 |
elif isinstance(msg, ToolMessage):
|
| 137 |
-
|
|
|
|
| 138 |
else:
|
| 139 |
result.append(msg.content)
|
| 140 |
|
|
@@ -177,7 +180,12 @@ def ask_jarvis(prompt: str, model: ModelEnum = DEFAULT_MODEL, thread_id: str = "
|
|
| 177 |
session_key = (model, thread_id)
|
| 178 |
if session_key not in _sessions_cache:
|
| 179 |
_sessions_cache[session_key] = JarvisSession(model, thread_id)
|
| 180 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 181 |
|
| 182 |
|
| 183 |
def reset_cache():
|
|
|
|
| 14 |
STARTING_CHAT = "STARTING_CHAT"
|
| 15 |
INITIALIZED = "INITIALIZED"
|
| 16 |
|
| 17 |
+
not_verbosed_tools = ["get_upcoming_events_tool"]
|
| 18 |
+
|
| 19 |
|
| 20 |
# === Global caches ===
|
| 21 |
_sessions_cache: dict[tuple[ModelEnum, str], "JarvisSession"] = {}
|
|
|
|
| 112 |
return {"role": role, "content": content}
|
| 113 |
|
| 114 |
def _build_agent_kwargs(self, messages: list) -> dict:
|
| 115 |
+
kwargs = {"input": {"messages": messages, "real_name": self.user["real_name"]}}
|
| 116 |
if self.model_enum in models_with_memory:
|
| 117 |
kwargs["config"] = {"configurable": {"thread_id": self.thread_id}}
|
| 118 |
return kwargs
|
|
|
|
| 136 |
for tool_call in msg.additional_kwargs['tool_calls']:
|
| 137 |
result.append(f"Llamando a la función: {tool_call['function']['name']}")
|
| 138 |
elif isinstance(msg, ToolMessage):
|
| 139 |
+
if not msg.name in not_verbosed_tools:
|
| 140 |
+
result.append(f"Resultado de la función {msg.name}: {msg.content}")
|
| 141 |
else:
|
| 142 |
result.append(msg.content)
|
| 143 |
|
|
|
|
| 180 |
session_key = (model, thread_id)
|
| 181 |
if session_key not in _sessions_cache:
|
| 182 |
_sessions_cache[session_key] = JarvisSession(model, thread_id)
|
| 183 |
+
result = _sessions_cache[session_key].ask(prompt)
|
| 184 |
+
|
| 185 |
+
if isinstance(result, list):
|
| 186 |
+
return result
|
| 187 |
+
else:
|
| 188 |
+
return [result]
|
| 189 |
|
| 190 |
|
| 191 |
def reset_cache():
|
api/google_api/jarvis_google_authentication.py
CHANGED
|
@@ -15,6 +15,9 @@ GOOGLE_API_DIR = os.path.join(PROJECT_ROOT, "api", "google_api")
|
|
| 15 |
|
| 16 |
def get_authentications_for_user(username, allow_logging_popup=False):
|
| 17 |
authentications = {}
|
|
|
|
|
|
|
|
|
|
| 18 |
for account in os.listdir(os.path.join(GOOGLE_API_DIR, username)):
|
| 19 |
for filename in os.listdir(os.path.join(GOOGLE_API_DIR, username, account)):
|
| 20 |
if filename.endswith(".json") and not "example" in filename:
|
|
|
|
| 15 |
|
| 16 |
def get_authentications_for_user(username, allow_logging_popup=False):
|
| 17 |
authentications = {}
|
| 18 |
+
|
| 19 |
+
if not os.path.isdir(os.path.join(GOOGLE_API_DIR, username)):
|
| 20 |
+
raise FileNotFoundError(f"No existe el directorio para el usuario '{username}'. Ruta comprobada: {os.path.join(GOOGLE_API_DIR, username)}")
|
| 21 |
for account in os.listdir(os.path.join(GOOGLE_API_DIR, username)):
|
| 22 |
for filename in os.listdir(os.path.join(GOOGLE_API_DIR, username, account)):
|
| 23 |
if filename.endswith(".json") and not "example" in filename:
|
tools/google_calendar.py
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import datetime
|
| 2 |
+
from langchain_core.tools import tool
|
| 3 |
+
from googleapiclient.discovery import build
|
| 4 |
+
from typing_extensions import Annotated
|
| 5 |
+
from langgraph.prebuilt import InjectedState
|
| 6 |
+
|
| 7 |
+
from api.google_api.jarvis_google_authentication import get_authentications_for_user
|
| 8 |
+
|
| 9 |
+
@tool
|
| 10 |
+
def get_upcoming_events_tool(
|
| 11 |
+
real_name: Annotated[str, InjectedState("real_name")],
|
| 12 |
+
num_events: int = 10
|
| 13 |
+
) -> str:
|
| 14 |
+
"""
|
| 15 |
+
Get the next upcoming events from the user's Google Calendar.
|
| 16 |
+
The parameter real_name is the real_name defined for the user.
|
| 17 |
+
The number of events to return can be specified with num_events.
|
| 18 |
+
"""
|
| 19 |
+
real_name = real_name.strip().lower()
|
| 20 |
+
authentications = get_authentications_for_user(real_name, allow_logging_popup=True)
|
| 21 |
+
events = []
|
| 22 |
+
for authentication in authentications.values():
|
| 23 |
+
service = build("calendar", "v3", credentials=authentication)
|
| 24 |
+
now = datetime.datetime.now(tz=datetime.timezone.utc).isoformat()
|
| 25 |
+
events_result = (
|
| 26 |
+
service.events()
|
| 27 |
+
.list(
|
| 28 |
+
calendarId="primary",
|
| 29 |
+
timeMin=now,
|
| 30 |
+
maxResults=num_events,
|
| 31 |
+
singleEvents=True,
|
| 32 |
+
orderBy="startTime",
|
| 33 |
+
)
|
| 34 |
+
.execute()
|
| 35 |
+
)
|
| 36 |
+
events.extend(events_result.get("items", []))
|
| 37 |
+
|
| 38 |
+
if not events:
|
| 39 |
+
return "No upcoming events found."
|
| 40 |
+
|
| 41 |
+
events = sorted(events,key=lambda event: event["start"].get('dateTime', event["start"].get('date')), reverse=False)
|
| 42 |
+
events = events[:num_events] if len(events) > num_events else events
|
| 43 |
+
|
| 44 |
+
result = ""
|
| 45 |
+
for event in events:
|
| 46 |
+
result += f"{event['start'].get('dateTime', event['start'].get('date'))} - {event['summary']}\n"
|
| 47 |
+
|
| 48 |
+
return result.strip()
|