Repository Public
1const SECRET = /xai-[A-Za-z0-9]{20,}/g;23function clean(v: unknown): unknown {4 if (typeof v === "string") return v.replace(SECRET, "xai-[redacted]");5 if (v instanceof Error) return { name: v.name, message: v.message.replace(SECRET, "xai-[redacted]") };6 if (Array.isArray(v)) return v.map(clean);7 if (v && typeof v === "object") {8 const o: Record<string, unknown> = {};9 for (const [k, x] of Object.entries(v)) o[k] = /authorization|api[_-]?key|password|secret|token/i.test(k) ? "[redacted]" : clean(x);10 return o;11 }12 return v;13}1415/** Structured JSON-lines logger with secret redaction. */16export function log(level: "info" | "warn" | "error", msg: string, fields: Record<string, unknown> = {}) {17 // CLIP_QUIET: tools whose stdout is machine-read (the director CLI) keep it clean; errors still go to stderr.18 if (process.env.CLIP_QUIET && level !== "error") return;19 const line = JSON.stringify({ t: new Date().toISOString(), level, msg, ...(clean(fields) as object) });20 if (level === "error") console.error(line); else console.log(line);21}22export const redact = (s: string) => s.replace(SECRET, "xai-[redacted]");23