ai-memory-backend / tools /gdrive_tool.py
Baida07's picture
sync: 171 files from Baida98/AI [deploy-all]
24480a0 verified
Raw
History Blame
4.86 kB
"""backend/tools/gdrive_tool.py — Google Drive Tier 3 Memory Tool.
Consente all'agente di archiviare e recuperare dati da Google Drive.
Ottimizzato per sessioni lunghe e offloading di memoria.
"""
import os, json, logging, httpx
from typing import Any, Optional
from api.auth_managed import _decrypt, _sb_list_tokens
_logger = logging.getLogger("gdrive_tool")
_TIMEOUT = 20.0
async def gdrive_rw(
action: str,
filename: Optional[str] = None,
content: Optional[str] = None,
file_id: Optional[str] = None,
query: Optional[str] = None,
user_id: str = "default"
) -> dict[str, Any]:
"""
Gestisce file su Google Drive per memoria a lungo termine.
action: search, read, write, update
"""
try:
# 1. Recupera token Google
tokens = await _sb_list_tokens(user_id)
g_token = next((t for t in tokens if t['provider'] == 'google'), None)
if not g_token:
return {"ok": False, "error": "[CONNECTOR_NEEDED:google] Connetti Google Drive per usare la memoria Tier 3"}
access_token = _decrypt(g_token['access_token'])
headers = {"Authorization": f"Bearer {access_token}", "Accept": "application/json"}
async with httpx.AsyncClient(timeout=_TIMEOUT) as client:
# --- SEARCH ---
if action == "search":
q = f"name contains '{query}'" if query else "mimeType = 'text/plain'"
r = await client.get(
"https://www.googleapis.com/drive/v3/files",
params={"q": q, "fields": "files(id, name, modifiedTime)"},
headers=headers
)
if r.status_code != 200:
return {"ok": False, "error": f"Drive Search Error: {r.text[:200]}"}
return {"ok": True, "files": r.json().get("files", [])}
# --- READ ---
elif action == "read":
if not file_id: return {"ok": False, "error": "file_id mancante"}
r = await client.get(f"https://www.googleapis.com/drive/v3/files/{file_id}?alt=media", headers=headers)
if r.status_code != 200:
return {"ok": False, "error": f"Drive Read Error: {r.text[:200]}"}
return {"ok": True, "content": r.text}
# --- WRITE (Create) ---
elif action == "write":
if not filename: return {"ok": False, "error": "filename mancante"}
meta = {"name": filename, "mimeType": "text/plain"}
files = {'data': ('metadata', json.dumps(meta), 'application/json'),
'file': (filename, content or "", 'text/plain')}
r = await client.post("https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart",
headers={"Authorization": f"Bearer {access_token}"}, files=files)
if r.status_code not in (200, 201):
return {"ok": False, "error": f"Drive Write Error: {r.text[:200]}"}
return {"ok": True, "file_id": r.json().get("id"), "message": f"File {filename} creato su Drive"}
# --- UPDATE ---
elif action == "update":
if not file_id: return {"ok": False, "error": "file_id mancante"}
r = await client.patch(f"https://www.googleapis.com/upload/drive/v3/files/{file_id}?uploadType=media",
headers=headers, content=content or "")
if r.status_code != 200:
return {"ok": False, "error": f"Drive Update Error: {r.text[:200]}"}
return {"ok": True, "message": "File aggiornato su Drive"}
return {"ok": False, "error": f"Azione {action} non supportata"}
except Exception as e:
_logger.error("GDrive Tool Error: %s", e)
return {"ok": False, "error": str(e)}
TOOL_DESCRIPTOR = {
"name": "gdrive_memory",
"description": (
"Gestisce la memoria a lungo termine su Google Drive (Tier 3). "
"Usa per archiviare contesti pesanti, log o file che superano i limiti di memoria locale. "
"Azioni: write (crea), read (legge), search (cerca), update (aggiorna)."
),
"parameters": {
"type": "object",
"properties": {
"action": {"type": "string", "enum": ["write", "read", "search", "update"]},
"filename": {"type": "string", "description": "Nome del file (es. session_memory_2026.txt)"},
"content": {"type": "string", "description": "Contenuto da archiviare"},
"file_id": {"type": "string", "description": "ID del file Drive per read/update"},
"query": {"type": "string", "description": "Termine di ricerca per action=search"}
},
"required": ["action"]
},
"fn": gdrive_rw
}