Record local agent reasoning and tool activity
Tests / Test apps.device-host-agent.tests.test_mcp_token.test_load_or_create_concurrent_calls_do_not_corrupt failed
Tests / Test apps.device-host-agent.tests.test_mcp_token.test_load_or_create_concurrent_calls_do_not_corrupt failed
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from datetime import UTC, datetime
|
||||
from pathlib import Path
|
||||
from threading import Lock
|
||||
from typing import Any
|
||||
|
||||
|
||||
class ConversationLogStore:
|
||||
"""Append-only local audit log for chat and tool activity."""
|
||||
|
||||
def __init__(self, path: str | Path) -> None:
|
||||
self.path = Path(path)
|
||||
self._lock = Lock()
|
||||
|
||||
def append(self, event: dict[str, Any]) -> None:
|
||||
record = {"timestamp": datetime.now(UTC).isoformat(), **_safe(event)}
|
||||
self.path.parent.mkdir(parents=True, exist_ok=True)
|
||||
with self._lock, self.path.open("a", encoding="utf-8") as stream:
|
||||
stream.write(json.dumps(record, ensure_ascii=True, default=str) + "\n")
|
||||
|
||||
|
||||
def _safe(value: Any) -> Any:
|
||||
if isinstance(value, dict):
|
||||
return {str(k): _safe(v) for k, v in value.items()}
|
||||
if isinstance(value, list):
|
||||
return [_safe(v) for v in value]
|
||||
return value if isinstance(value, (str, int, float, bool)) or value is None else str(value)
|
||||
Reference in New Issue
Block a user