Files
plugin-registry/plugins/conversation-logger/hooks/after_turn.py
T
ixoblakp 8dec8f6038 Initial Arka plugin registry: Official plugins mirror + Arka-signed index
11 plugins from github.com/librefang/librefang-registry plugins/.
index.json / index.json.sig are signed with Arka's Ed25519 key
(not upstream stats.librefang.ai). Private key is not in this repo.
2026-09-01 10:22:07 +03:00

69 lines
2.1 KiB
Python

#!/usr/bin/env python3
"""Conversation logger after_turn hook.
Appends a JSON line to a per-agent log file after each conversation turn.
Log files are stored under ~/.librefang/logs/conversations/{agent_id}.jsonl.
Receives via stdin:
{"type": "after_turn", "agent_id": "...", "messages": [...]}
Prints to stdout:
{"type": "ok"}
"""
import json
import os
import sys
from datetime import datetime, timezone
from pathlib import Path
def _log_dir() -> Path:
"""Return the conversations log directory, creating it if needed."""
home = Path.home()
log_path = home / ".librefang" / "logs" / "conversations"
log_path.mkdir(parents=True, exist_ok=True)
return log_path
def _last_message_by_role(messages: list, role: str) -> str:
"""Find the last message with the given role and return its content truncated to 200 chars."""
for msg in reversed(messages):
if msg.get("role") == role:
content = msg.get("content", "")
if len(content) > 200:
return content[:200] + "..."
return content
return ""
def main():
request = json.loads(sys.stdin.read())
agent_id = request.get("agent_id", "unknown")
messages = request.get("messages", [])
entry = {
"timestamp": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
"agent_id": agent_id,
"turn_number": max(
sum(1 for m in messages if m.get("role") == "assistant"), 1
),
"message_count": len(messages),
"last_user_message": _last_message_by_role(messages, "user"),
"last_assistant_message": _last_message_by_role(messages, "assistant"),
}
try:
log_file = _log_dir() / f"{agent_id}.jsonl"
with open(log_file, "a", encoding="utf-8") as f:
f.write(json.dumps(entry, ensure_ascii=False) + "\n")
except OSError:
# Filesystem issues should not crash the agent. The hook still
# responds with "ok" so the conversation continues normally.
pass
print(json.dumps({"type": "ok"}))
if __name__ == "__main__":
main()