from __future__ import annotations import json from datetime import datetime, timezone from pathlib import Path from typing import Any from time_machine.domain.events import TemporalEvent class JsonlTraceSink: def __init__(self, path: Path) -> None: self.path = path self.path.parent.mkdir(parents=True, exist_ok=True) if not self.path.exists(): self.path.touch() def record_event(self, event: TemporalEvent) -> None: self._write({"kind": "event", "event": event.model_dump(mode="json")}) def record_model_io( self, component: str, prompt: str, raw_output: str, parsed_output: Any, metadata: dict[str, Any] | None = None, ) -> None: self._write( { "kind": "model_io", "component": component, "prompt": prompt, "raw_output": raw_output, "parsed_output": parsed_output, "metadata": metadata or {}, } ) def _write(self, record: dict[str, Any]) -> None: record["created_at"] = datetime.now(timezone.utc).isoformat() with self.path.open("a", encoding="utf-8") as handle: handle.write(json.dumps(record, ensure_ascii=True) + "\n")