Connector calls, semantic rules, and DuckDB memory keep long runs stable, and stream retry stops chats from stalling. Co-authored-by: Cursor <cursoragent@cursor.com>
43 lines
1.1 KiB
Python
43 lines
1.1 KiB
Python
"""Redact secrets from connector observations and logs."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import re
|
|
from typing import Any, Dict
|
|
|
|
_SECRET_KEYS = re.compile(
|
|
r"(apikey|api_key|authorization|set-cookie|cookie|token|password|secret)",
|
|
re.IGNORECASE,
|
|
)
|
|
_QUERY_SECRET = re.compile(
|
|
r"(?i)(apikey|api_key|token|password|secret)=([^&\s\"']+)"
|
|
)
|
|
|
|
|
|
def redact_text(value: str) -> str:
|
|
return _QUERY_SECRET.sub(r"\1=***", value)
|
|
|
|
|
|
def redact(value: Any) -> Any:
|
|
if isinstance(value, dict):
|
|
cleaned = {}
|
|
for key, item in value.items():
|
|
if _SECRET_KEYS.search(str(key)):
|
|
cleaned[key] = "***"
|
|
else:
|
|
cleaned[key] = redact(item)
|
|
return cleaned
|
|
if isinstance(value, list):
|
|
return [redact(item) for item in value]
|
|
if isinstance(value, str):
|
|
return redact_text(value)
|
|
return value
|
|
|
|
|
|
def strip_sensitive_fields(body: Dict[str, Any]) -> Dict[str, Any]:
|
|
return {
|
|
key: value
|
|
for key, value in body.items()
|
|
if not _SECRET_KEYS.search(str(key))
|
|
}
|