File size: 2,991 Bytes
c596990
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f52cdc8
c596990
f52cdc8
c596990
f52cdc8
c596990
 
 
f52cdc8
c596990
 
 
 
 
 
 
 
 
f52cdc8
c596990
 
 
f52cdc8
c596990
 
 
d59f526
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import redis
import hashlib
import json
import os
from logger import get_logger

logger = get_logger("cache")

def get_redis_client():
    url = os.environ.get("REDIS_URL")
    if not url:
        return None
    try:
        client = redis.from_url(url, decode_responses=True, socket_timeout=2)
        client.ping()
        return client
    except Exception as e:
        logger.warning("Redis unavailable", extra={"event": "cache_unavailable", "error": str(e)})
        return None

r = get_redis_client()
CACHE_TTL = 3600

def make_cache_key(message: str, thread_id: str = "global") -> str:
    normalized = message.lower().strip()
    return "agent:v1:" + hashlib.sha256(f"{thread_id}:{normalized}".encode()).hexdigest()

def get_cached_response(message: str, thread_id: str = "global") -> dict | None:
    if r is None:
        return None
    try:
        key = make_cache_key(message, thread_id)
        value = r.get(key)
        if value:
            logger.info("Cache hit", extra={"event": "cache_hit"})
            return json.loads(value)
        return None
    except Exception as e:
        logger.warning("Cache get failed", extra={"event": "cache_error", "error": str(e)})
        return None

def set_cached_response(message: str, response: dict, thread_id: str = "global") -> None:
    if r is None:
        return
    try:
        key = make_cache_key(message, thread_id)
        r.setex(key, CACHE_TTL, json.dumps(response))
        logger.info("Cache set", extra={"event": "cache_set"})
    except Exception as e:
        logger.warning("Cache set failed", extra={"event": "cache_error", "error": str(e)})

# --- Tool-level caching ---
TOOL_CACHE_TTL = 120  # 2 minutes — short TTL for data freshness

def make_tool_cache_key(tool_name: str, args: dict) -> str:
    """Create a cache key from tool name + sorted args."""
    args_str = json.dumps(args, sort_keys=True).lower().strip()
    return "tool:v1:" + hashlib.sha256(f"{tool_name}:{args_str}".encode()).hexdigest()

def get_cached_tool_result(tool_name: str, args: dict) -> str | None:
    if r is None:
        return None
    try:
        key = make_tool_cache_key(tool_name, args)
        value = r.get(key)
        if value:
            logger.info("Tool cache hit", extra={
                "event": "tool_cache_hit", "tool": tool_name
            })
            return value
        return None
    except Exception as e:
        logger.warning("Tool cache get failed", extra={"event": "tool_cache_error", "error": str(e)})
        return None

def set_cached_tool_result(tool_name: str, args: dict, result: str) -> None:
    if r is None:
        return
    try:
        key = make_tool_cache_key(tool_name, args)
        r.setex(key, TOOL_CACHE_TTL, result)
        logger.info("Tool cache set", extra={
            "event": "tool_cache_set", "tool": tool_name
        })
    except Exception as e:
        logger.warning("Tool cache set failed", extra={"event": "tool_cache_error", "error": str(e)})