Files
true-recall/tr-compact/hook.py

105 lines
2.6 KiB
Python

#!/usr/bin/env python3
"""
TrueRecall v2 - Compaction Hook
Fast Redis queue push for compaction events
Called by OpenClaw session_before_compact hook
"""
import json
import sys
import redis
from datetime import datetime
from typing import List, Dict, Any
# Redis config
REDIS_HOST = "10.0.0.36"
REDIS_PORT = 6379
REDIS_DB = 0
QUEUE_KEY = "tr:compact_queue"
TAG_PREFIX = "tr:processed"
def get_redis_client():
return redis.Redis(
host=REDIS_HOST,
port=REDIS_PORT,
db=REDIS_DB,
decode_responses=True
)
def tag_turns(messages: List[Dict], user_id: str = "rob"):
"""Tag turns so v1 daily curator skips them"""
r = get_redis_client()
pipe = r.pipeline()
for msg in messages:
conv_id = msg.get("conversation_id", "unknown")
turn = msg.get("turn", 0)
tag_key = f"{TAG_PREFIX}:{conv_id}:{turn}"
pipe.setex(tag_key, 86400, "1") # 24h TTL
pipe.execute()
def queue_messages(messages: List[Dict], user_id: str = "rob"):
"""Push messages to Redis queue for background processing"""
r = get_redis_client()
queue_item = {
"user_id": user_id,
"timestamp": datetime.now().isoformat(),
"message_count": len(messages),
"messages": messages
}
# LPUSH to queue (newest first)
r.lpush(QUEUE_KEY, json.dumps(queue_item))
return len(messages)
def process_compaction_event(event_data: Dict):
"""
Process session_before_compact event from OpenClaw
Expected event_data:
{
"session_id": "uuid",
"user_id": "rob",
"messages_being_compacted": [
{"role": "user", "content": "...", "turn": 1, "conversation_id": "..."},
...
],
"compaction_reason": "context_limit"
}
"""
user_id = event_data.get("user_id", "rob")
messages = event_data.get("messages_being_compacted", [])
if not messages:
return {"status": "ok", "queued": 0, "reason": "no_messages"}
# Tag turns for v1 coordination
tag_turns(messages, user_id)
# Queue for background processing
count = queue_messages(messages, user_id)
return {
"status": "ok",
"queued": count,
"user_id": user_id,
"queue_key": QUEUE_KEY
}
def main():
"""CLI entry point - reads JSON from stdin"""
try:
event_data = json.load(sys.stdin)
result = process_compaction_event(event_data)
print(json.dumps(result))
sys.exit(0)
except Exception as e:
print(json.dumps({"status": "error", "error": str(e)}))
sys.exit(1)
if __name__ == "__main__":
main()