555e282cc4
ci / changelog_check (push) Waiting to run
ci / check_changes (push) Waiting to run
ci / build_mem0 (3.10) (push) Blocked by required conditions
ci / build_mem0 (3.11) (push) Blocked by required conditions
ci / build_mem0 (3.12) (push) Blocked by required conditions
CLI Node CI / lint (push) Waiting to run
CLI Node CI / test (20) (push) Waiting to run
CLI Node CI / test (22) (push) Waiting to run
CLI Node CI / build (push) Waiting to run
CLI Python CI / lint (push) Waiting to run
CLI Python CI / test (3.10) (push) Waiting to run
CLI Python CI / test (3.11) (push) Waiting to run
CLI Python CI / test (3.12) (push) Waiting to run
CLI Python CI / build (push) Waiting to run
openclaw checks / lint (push) Waiting to run
openclaw checks / test (20) (push) Waiting to run
openclaw checks / test (22) (push) Waiting to run
openclaw checks / build (push) Waiting to run
opencode-plugin checks / build (push) Waiting to run
pi-agent-plugin checks / lint (push) Waiting to run
pi-agent-plugin checks / test (20) (push) Waiting to run
pi-agent-plugin checks / test (22) (push) Waiting to run
pi-agent-plugin checks / build (push) Waiting to run
TypeScript SDK CI / check_changes (push) Waiting to run
TypeScript SDK CI / changelog_check (push) Blocked by required conditions
TypeScript SDK CI / build_ts_sdk (20) (push) Blocked by required conditions
TypeScript SDK CI / build_ts_sdk (22) (push) Blocked by required conditions
TypeScript SDK CI / integration_ts_sdk (20) (push) Blocked by required conditions
TypeScript SDK CI / integration_ts_sdk (22) (push) Blocked by required conditions
107 lines
3.1 KiB
Python
107 lines
3.1 KiB
Python
#!/usr/bin/env python3
|
|
"""Fetch recent memories and format a compact timeline for SessionStart.
|
|
|
|
Searches mem0 cloud API for the most recent memories in the project
|
|
and formats them as a compact activity timeline injected below the
|
|
existing SessionStart banner.
|
|
|
|
Input: env vars for identity (MEM0_API_KEY, MEM0_RESOLVED_USER_ID, etc.)
|
|
Output: Compact timeline text to stdout (empty if nothing found)
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import os
|
|
import sys
|
|
import urllib.request
|
|
|
|
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
|
from _formatting import TYPE_ICONS, format_age
|
|
from _identity import resolve_api_key, resolve_user_id
|
|
from _project import resolve_project_id
|
|
|
|
API_URL = "https://api.mem0.ai"
|
|
MAX_RECENT = 10
|
|
MAX_SUMMARIES = 3
|
|
FETCH_TIMEOUT = 5
|
|
|
|
|
|
def fetch_recent_memories(api_key: str, user_id: str, project_id: str) -> list[dict]:
|
|
"""Fetch the most recent memories for this project via GET list endpoint."""
|
|
global_search = os.environ.get("MEM0_GLOBAL_SEARCH", "false") == "true"
|
|
|
|
if global_search:
|
|
filters = {"OR": [{"user_id": "*"}]}
|
|
else:
|
|
filters = {"AND": [{"user_id": user_id}, {"app_id": project_id}]}
|
|
|
|
body = json.dumps({"filters": filters}).encode()
|
|
req = urllib.request.Request(
|
|
f"{API_URL}/v3/memories/?page=1&page_size={MAX_RECENT}",
|
|
data=body,
|
|
headers={
|
|
"Authorization": f"Token {api_key}",
|
|
"Content-Type": "application/json",
|
|
},
|
|
method="POST",
|
|
)
|
|
try:
|
|
with urllib.request.urlopen(req, timeout=FETCH_TIMEOUT) as r:
|
|
result = json.loads(r.read())
|
|
if isinstance(result, dict) and "results" in result:
|
|
return result["results"][:MAX_RECENT]
|
|
if isinstance(result, list):
|
|
return result[:MAX_RECENT]
|
|
return []
|
|
except Exception:
|
|
return []
|
|
|
|
|
|
def format_timeline(memories: list[dict]) -> str:
|
|
"""Format memories into a compact recent activity timeline."""
|
|
if not memories:
|
|
return ""
|
|
|
|
lines = ["### Recent Activity", ""]
|
|
|
|
for m in memories:
|
|
mid = m.get("id", "?")[:8]
|
|
text = (m.get("memory", "") or "")[:120].replace("\n", " ").strip()
|
|
meta = m.get("metadata") or {}
|
|
cat = meta.get("type", "unknown")
|
|
icon = TYPE_ICONS.get(cat, "❓")
|
|
age = format_age(m)
|
|
age_str = f" ({age})" if age else ""
|
|
lines.append(f"- {icon} [{cat}]{age_str} {text} [mem0:{mid}]")
|
|
|
|
lines.append("")
|
|
lines.append("Search mem0 for details on any of these, or for past decisions and task learnings relevant to the current task.")
|
|
|
|
return "\n".join(lines)
|
|
|
|
|
|
def main():
|
|
api_key = resolve_api_key()
|
|
if not api_key:
|
|
return
|
|
|
|
user_id = resolve_user_id()
|
|
project_id = resolve_project_id(os.environ.get("MEM0_CWD"))
|
|
|
|
memories = fetch_recent_memories(api_key, user_id, project_id)
|
|
if not memories:
|
|
return
|
|
|
|
timeline = format_timeline(memories)
|
|
if timeline:
|
|
print(timeline, end="")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
try:
|
|
main()
|
|
except Exception:
|
|
pass
|
|
sys.exit(0)
|