105 lines
2.6 KiB
Python
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() |