mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-18 21:54:49 +00:00
Merged via squash.
Prepared head SHA: da91ab6cf1
Co-authored-by: app/clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: hxy91819 <8814856+hxy91819@users.noreply.github.com>
Reviewed-by: @hxy91819
109 lines
3.2 KiB
TypeScript
109 lines
3.2 KiB
TypeScript
import type { AgentMessage } from "@earendil-works/pi-agent-core";
|
|
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
|
import { readLoggingConfig } from "../logging/config.js";
|
|
import {
|
|
getDefaultRedactPatterns,
|
|
redactSensitiveFieldValue,
|
|
redactSensitiveText,
|
|
} from "../logging/redact.js";
|
|
|
|
function resolveTranscriptRedactPatterns(patterns?: string[]) {
|
|
return patterns && patterns.length > 0 ? [...patterns, ...getDefaultRedactPatterns()] : undefined;
|
|
}
|
|
|
|
function redactTranscriptOptions(cfg?: OpenClawConfig) {
|
|
const configuredLogging = readLoggingConfig();
|
|
const mode = cfg?.logging?.redactSensitive ?? configuredLogging?.redactSensitive;
|
|
const patterns = resolveTranscriptRedactPatterns(
|
|
cfg?.logging?.redactPatterns ?? configuredLogging?.redactPatterns,
|
|
);
|
|
if (mode === undefined && patterns === undefined) {
|
|
return undefined;
|
|
}
|
|
return {
|
|
...(mode !== undefined ? { mode } : {}),
|
|
...(patterns !== undefined ? { patterns } : {}),
|
|
};
|
|
}
|
|
|
|
function redactTranscriptText(value: string, cfg?: OpenClawConfig): string {
|
|
if (cfg?.logging?.redactSensitive === "off") {
|
|
return value;
|
|
}
|
|
return redactSensitiveText(value, redactTranscriptOptions(cfg));
|
|
}
|
|
|
|
function redactTranscriptStructuredFieldValue(
|
|
key: string,
|
|
value: string,
|
|
cfg?: OpenClawConfig,
|
|
): string {
|
|
if (cfg?.logging?.redactSensitive === "off") {
|
|
return value;
|
|
}
|
|
return redactSensitiveFieldValue(key, value, redactTranscriptOptions(cfg));
|
|
}
|
|
|
|
function isPlainTranscriptObject(value: object): value is Record<string, unknown> {
|
|
const prototype = Object.getPrototypeOf(value);
|
|
return prototype === Object.prototype || prototype === null;
|
|
}
|
|
|
|
function redactTranscriptStructuredValue(
|
|
value: unknown,
|
|
cfg?: OpenClawConfig,
|
|
fieldKey?: string,
|
|
seen: WeakSet<object> = new WeakSet<object>(),
|
|
): unknown {
|
|
if (typeof value === "string") {
|
|
if (fieldKey) {
|
|
return redactTranscriptStructuredFieldValue(fieldKey, value, cfg);
|
|
}
|
|
return redactTranscriptText(value, cfg);
|
|
}
|
|
if (Array.isArray(value)) {
|
|
if (seen.has(value)) {
|
|
return "[Circular]";
|
|
}
|
|
seen.add(value);
|
|
let changed = false;
|
|
const redacted = value.map((item) => {
|
|
const next = redactTranscriptStructuredValue(item, cfg, fieldKey, seen);
|
|
changed ||= next !== item;
|
|
return next;
|
|
});
|
|
seen.delete(value);
|
|
return changed ? redacted : value;
|
|
}
|
|
if (!value || typeof value !== "object") {
|
|
return value;
|
|
}
|
|
if (seen.has(value)) {
|
|
return "[Circular]";
|
|
}
|
|
if (!isPlainTranscriptObject(value)) {
|
|
return value;
|
|
}
|
|
|
|
seen.add(value);
|
|
const source = value;
|
|
let next: Record<string, unknown> | null = null;
|
|
for (const [key, item] of Object.entries(source)) {
|
|
const redacted = redactTranscriptStructuredValue(item, cfg, key, seen);
|
|
if (redacted === item) {
|
|
continue;
|
|
}
|
|
next ??= { ...source };
|
|
next[key] = redacted;
|
|
}
|
|
seen.delete(value);
|
|
return next ?? value;
|
|
}
|
|
|
|
export function redactTranscriptMessage(message: AgentMessage, cfg?: OpenClawConfig): AgentMessage {
|
|
if (cfg?.logging?.redactSensitive === "off") {
|
|
return message;
|
|
}
|
|
return redactTranscriptStructuredValue(message, cfg) as AgentMessage;
|
|
}
|