119 lines
3.5 KiB
Python
119 lines
3.5 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Backup MEMORY.md and daily memory files to Supermemory
|
|
Runs via cron every 6 hours
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import requests
|
|
from datetime import datetime
|
|
from pathlib import Path
|
|
|
|
# Load API key from .env file manually
|
|
def load_env():
|
|
# Get the directory where this script is located
|
|
script_dir = Path(__file__).parent
|
|
# Look for .env in the parent directory (workspace root)
|
|
env_path = script_dir.parent / '.env'
|
|
if env_path.exists():
|
|
with open(env_path, 'r') as f:
|
|
for line in f:
|
|
if line.strip() and not line.startswith('#'):
|
|
if '=' in line:
|
|
key, value = line.strip().split('=', 1)
|
|
os.environ[key] = value
|
|
|
|
load_env()
|
|
API_KEY = os.getenv('SUPERMEMORY_API_KEY')
|
|
|
|
if not API_KEY:
|
|
print("Error: SUPERMEMORY_API_KEY not found in .env")
|
|
sys.exit(1)
|
|
|
|
API_BASE = "https://api.supermemory.ai/v3"
|
|
HEADERS = {
|
|
"Authorization": f"Bearer {API_KEY}",
|
|
"Content-Type": "application/json"
|
|
}
|
|
|
|
def read_file(path):
|
|
"""Read file content, return None if not found"""
|
|
try:
|
|
with open(path, 'r', encoding='utf-8') as f:
|
|
return f.read()
|
|
except UnicodeDecodeError:
|
|
# Fallback to Windows-1252 for files with em-dashes, etc.
|
|
try:
|
|
with open(path, 'r', encoding='cp1252') as f:
|
|
return f.read()
|
|
except:
|
|
return None
|
|
except FileNotFoundError:
|
|
return None
|
|
|
|
def backup_to_supermemory():
|
|
"""Backup memory files to Supermemory"""
|
|
|
|
# Get workspace directory (parent of script directory)
|
|
workspace_dir = Path(__file__).parent.parent
|
|
|
|
# Read MEMORY.md
|
|
memory_content = read_file(workspace_dir / 'MEMORY.md')
|
|
|
|
# Read today's memory file
|
|
today = datetime.now().strftime('%Y-%m-%d')
|
|
daily_memory = read_file(workspace_dir / 'memory' / f'{today}.md')
|
|
|
|
if not memory_content and not daily_memory:
|
|
print("No memory files to backup")
|
|
return
|
|
|
|
# Combine content
|
|
full_backup = f"""# Memory Backup - {today}
|
|
|
|
## Long-term Memory (MEMORY.md)
|
|
{memory_content if memory_content else "(No long-term memory yet)"}
|
|
|
|
## Daily Notes (memory/{today}.md)
|
|
{daily_memory if daily_memory else "(No daily notes yet)"}
|
|
"""
|
|
|
|
# Use correct Supermemory endpoint: POST /v3/documents
|
|
payload = {
|
|
"content": full_backup,
|
|
"containerTag": "clawdbot-memory",
|
|
"customId": f"memory-backup-{today}",
|
|
"metadata": {
|
|
"type": "memory-backup",
|
|
"date": today,
|
|
"source": "clawdbot"
|
|
}
|
|
}
|
|
|
|
try:
|
|
response = requests.post(
|
|
f"{API_BASE}/documents",
|
|
headers=HEADERS,
|
|
json=payload,
|
|
timeout=30
|
|
)
|
|
|
|
if response.status_code == 200 or response.status_code == 201:
|
|
result = response.json()
|
|
print(f"[OK] Successfully backed up memory to Supermemory")
|
|
print(f" Document ID: {result.get('id', 'unknown')}")
|
|
print(f" Status: {result.get('status', 'unknown')}")
|
|
# Write backup timestamp
|
|
with open('.last-backup', 'w') as f:
|
|
f.write(datetime.now().isoformat())
|
|
else:
|
|
print(f"[ERROR] Failed to backup: {response.status_code}")
|
|
print(f" Response: {response.text}")
|
|
|
|
except Exception as e:
|
|
print(f"[ERROR] Error backing up: {e}")
|
|
|
|
if __name__ == "__main__":
|
|
backup_to_supermemory()
|