"""Audit logging for AI tool calls. Reuses the application audit log (``data/audit.log``, JSON lines) and adds an ``ai_tool_call`` action. Argument values that may contain sensitive payloads (file content, prompts) are summarized rather than stored verbatim. """ from __future__ import annotations from datetime import datetime, timezone from typing import Any from backend.audit import _write_entry # Argument keys whose values may contain secrets or large payloads. _SENSITIVE_ARG_KEYS = {"content", "text", "body"} _MAX_ARG_CHARS = 200 def _sanitize_arguments(arguments: dict[str, Any] | None) -> dict[str, Any]: """Return a log-safe view of tool arguments.""" safe: dict[str, Any] = {} for key, value in (arguments or {}).items(): if key in _SENSITIVE_ARG_KEYS: safe[key] = f"<{len(str(value))} chars>" else: safe[key] = str(value)[:_MAX_ARG_CHARS] return safe def log_tool_call( *, username: str, mode: str, tool: str, arguments: dict[str, Any] | None = None, ok: bool = True, vault: str | None = None, ip: str | None = None, error: str | None = None, ) -> None: """Append an ``ai_tool_call`` entry to the audit log.""" _write_entry({ "timestamp": datetime.now(timezone.utc).isoformat(), "action": "ai_tool_call", "username": username, "ip": ip or "unknown", "mode": mode, "tool": tool, "vault": vault, "ok": ok, "error": error, "arguments": _sanitize_arguments(arguments), })