Files
memory-gateway/plugins/memory-gateway-agent/memory_gateway_plugin/output.py

87 lines
3.1 KiB
Python

from __future__ import annotations
import json
import os
from typing import Any
SENSITIVE_KEYS = ("api_key", "apikey", "authorization", "token", "cookie", "secret", "password", "x-api-key")
def debug_raw_enabled() -> bool:
return os.environ.get("MEMORY_GATEWAY_PLUGIN_DEBUG_RAW", "").strip().lower() in {"1", "true", "yes", "on"}
def short_id(value: Any, prefix: int = 8, suffix: int = 4) -> str:
text = "" if value is None else str(value)
if len(text) <= prefix + suffix + 3:
return text
return f"{text[:prefix]}...{text[-suffix:]}"
import re
def redact(value: Any) -> Any:
if isinstance(value, dict):
return {
key: ("<redacted>" if key.lower() in SENSITIVE_KEYS else redact(item))
for key, item in value.items()
}
if isinstance(value, list):
return [redact(item) for item in value]
if isinstance(value, str):
lowered = value.lower()
sensitive_markers = ("api_key=", "password=", "token=", "bearer ", "cookie:", "private key")
if any(marker in lowered for marker in sensitive_markers):
return "<redacted>"
return value
def summarize_data(data: Any) -> Any:
if debug_raw_enabled():
return redact(data)
if isinstance(data, list):
return {"count": len(data)}
if not isinstance(data, dict):
return data
if "results" in data:
return {
"count": len(data.get("results") or []),
"total": data.get("total"),
"local_total": data.get("local_total"),
"openviking_total": data.get("openviking_total"),
"searched_namespaces": data.get("searched_namespaces", []),
}
if "id" in data:
return {
"id": short_id(data.get("id")),
"namespace": data.get("namespace"),
"memory_type": data.get("memory_type"),
"source": data.get("source"),
}
if "memory_id" in data:
return {"status": data.get("status"), "memory_id": short_id(data.get("memory_id")), "feedback": data.get("feedback")}
if "promoted" in data or "consolidation" in data:
return {
"status": data.get("status"),
"promoted_count": len(data.get("promoted") or []),
"archived_count": len(data.get("archived_episode_ids") or []),
"consolidation_status": (data.get("consolidation") or {}).get("status") if isinstance(data.get("consolidation"), dict) else None,
}
allowed = {"ok", "status", "gateway", "service", "version", "healthy", "endpoint", "status_code", "error", "count"}
return {key: redact(value) for key, value in data.items() if key in allowed}
def summarize_result(result: dict[str, Any]) -> dict[str, Any]:
return {
"ok": bool(result.get("ok")),
"endpoint": result.get("endpoint"),
"status_code": result.get("status_code"),
"error": redact(result.get("error", "")),
"data": summarize_data(result.get("data")),
}
def dumps_safe(payload: Any, *, indent: int = 2) -> str:
return json.dumps(redact(payload), ensure_ascii=False, indent=indent, default=str)