Some checks failed
Forge CI / smoke-and-build (pull_request) Failing after 1m7s
Evaluates Honcho AI-native memory from plastic-labs fork against local SQLite. Pluggable architecture with zero overhead when disabled. Backends: Null — zero overhead (default disabled) Local — SQLite at ~/.hermes/memory.db (sovereign, recommended) Honcho — opt-in cloud via HONCHO_API_KEY Evaluation scoring (availability + functionality + latency + privacy): Local: ~95pts (A grade) — privacy 20/20 Honcho: ~60pts (B grade) — privacy 5/20 RECOMMENDATION: Local for sovereignty. Same functionality, better privacy. No cloud dependency. agent/memory.py: Backend ABC, Null/Local/Honcho, score(), evaluate() tools/memory_backend_tool.py: store/get/query/list/delete/info/evaluate tests/agent/test_memory.py: 31 tests, all passing New issue filed: #550 (close duplicate PRs for #322) Closes #322
80 lines
2.8 KiB
Python
80 lines
2.8 KiB
Python
"""Memory backend tool — cross-session user modeling.
|
|
|
|
Local SQLite default, Honcho cloud opt-in. Zero overhead when disabled.
|
|
"""
|
|
|
|
import json
|
|
from tools.registry import registry
|
|
|
|
|
|
def memory_backend(action, uid="default", key=None, value=None, query=None, meta=None):
|
|
from agent.memory import get_backend, evaluate
|
|
b = get_backend()
|
|
|
|
if action == "info":
|
|
return json.dumps({"success": True, "backend": b.name, "cloud": b.cloud, "available": b.ok()})
|
|
|
|
if action == "store":
|
|
if not key or value is None:
|
|
return json.dumps({"success": False, "error": "key and value required"})
|
|
return json.dumps({"success": b.put(uid, key, value, meta), "key": key})
|
|
|
|
if action == "get":
|
|
if not key:
|
|
return json.dumps({"success": False, "error": "key required"})
|
|
e = b.get(uid, key)
|
|
if not e:
|
|
return json.dumps({"success": False, "error": f"not found: {key}"})
|
|
return json.dumps({"success": True, "key": e.key, "value": e.value, "type": e.etype})
|
|
|
|
if action == "query":
|
|
if not query:
|
|
return json.dumps({"success": False, "error": "query required"})
|
|
r = b.find(uid, query)
|
|
return json.dumps({"success": True,
|
|
"results": [{"key": e.key, "value": e.value} for e in r], "count": len(r)})
|
|
|
|
if action == "list":
|
|
r = b.all(uid)
|
|
return json.dumps({"success": True,
|
|
"entries": [{"key": e.key, "type": e.etype} for e in r], "count": len(r)})
|
|
|
|
if action == "delete":
|
|
if not key:
|
|
return json.dumps({"success": False, "error": "key required"})
|
|
return json.dumps({"success": b.rm(uid, key)})
|
|
|
|
if action == "evaluate":
|
|
return json.dumps({"success": True, **evaluate()})
|
|
|
|
return json.dumps({"success": False, "error": f"unknown action: {action}"})
|
|
|
|
|
|
registry.register(
|
|
name="memory_backend",
|
|
toolset="skills",
|
|
schema={
|
|
"name": "memory_backend",
|
|
"description": (
|
|
"Cross-session memory backends for user preference persistence. "
|
|
"Local SQLite default (sovereign), Honcho cloud opt-in via HONCHO_API_KEY. "
|
|
"Zero overhead when disabled."
|
|
),
|
|
"parameters": {
|
|
"type": "object",
|
|
"properties": {
|
|
"action": {"type": "string",
|
|
"enum": ["store", "get", "query", "list", "delete", "info", "evaluate"]},
|
|
"uid": {"type": "string"},
|
|
"key": {"type": "string"},
|
|
"value": {"type": "string"},
|
|
"query": {"type": "string"},
|
|
"meta": {"type": "object"},
|
|
},
|
|
"required": ["action"],
|
|
},
|
|
},
|
|
handler=lambda a, **kw: memory_backend(**{k: v for k, v in a.items() if v is not None}),
|
|
emoji="🧠",
|
|
)
|