openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
153 lines (152 loc) • 7.04 kB
JavaScript
import { l as normalizeOptionalString, o as normalizeLowercaseStringOrEmpty } from "./string-coerce-CIXf7egm.js";
import { t as normalizeChatType } from "./chat-type-CG0X_HJM.js";
import { o as resolveUserTimezone } from "./date-time-C7YbYLih.js";
import { a as resolveTimezone, n as formatUtcTimestamp, r as formatZonedTimestamp } from "./format-datetime-xsAchuLA.js";
import { n as formatTimeAgo } from "./format-relative-DiD6ocfu.js";
//#region src/channels/sender-label.ts
function normalizeSenderLabelParams(params) {
return {
name: normalizeOptionalString(params.name),
username: normalizeOptionalString(params.username),
tag: normalizeOptionalString(params.tag),
e164: normalizeOptionalString(params.e164),
id: normalizeOptionalString(params.id)
};
}
const OPAQUE_UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/iu;
/** Resolves the best one-line sender label from available identity fields. */
function resolveSenderLabel(params) {
const { name, username, tag, e164, id } = normalizeSenderLabelParams(params);
const display = name ?? username ?? tag ?? "";
const idPart = e164 ?? id ?? "";
if (display && idPart && display !== idPart && !OPAQUE_UUID_RE.test(idPart)) return `${display} (${idPart})`;
return display || idPart || null;
}
//#endregion
//#region src/auto-reply/envelope.ts
/** Formats inbound message envelopes with sender, timing, and channel metadata for agent prompts. */
function sanitizeEnvelopeHeaderPart(value) {
return value.replace(/\r\n|\r|\n/g, " ").replaceAll("[", "(").replaceAll("]", ")").replace(/\s+/g, " ").trim();
}
/** Resolves envelope formatting defaults from agent config. */
function resolveEnvelopeFormatOptions(cfg) {
const defaults = cfg?.agents?.defaults;
const configuredTimezone = normalizeOptionalString(defaults?.userTimezone);
return {
timezone: configuredTimezone ? resolveTimezone(configuredTimezone) ?? "local" : void 0,
includeTimestamp: true,
includeElapsed: true,
userTimezone: defaults?.userTimezone
};
}
function normalizeEnvelopeOptions(options) {
const includeTimestamp = options?.includeTimestamp !== false;
const includeElapsed = options?.includeElapsed !== false;
return {
timezone: normalizeOptionalString(options?.timezone) || "local",
includeTimestamp,
includeElapsed,
userTimezone: options?.userTimezone
};
}
function resolveEnvelopeTimezone(options) {
const trimmed = options.timezone?.trim();
if (!trimmed) return { mode: "local" };
const lowered = normalizeLowercaseStringOrEmpty(trimmed);
if (lowered === "utc" || lowered === "gmt") return { mode: "utc" };
if (lowered === "local" || lowered === "host") return { mode: "local" };
if (lowered === "user") return {
mode: "iana",
timeZone: resolveUserTimezone(options.userTimezone)
};
const explicit = resolveTimezone(trimmed);
return explicit ? {
mode: "iana",
timeZone: explicit
} : { mode: "utc" };
}
/** Formats an envelope timestamp using local, UTC, user, or explicit IANA timezone rules. */
function formatAgentEnvelopeTimestamp(ts, options) {
if (ts === void 0) return;
const resolved = normalizeEnvelopeOptions(options);
if (!resolved.includeTimestamp) return;
const date = ts instanceof Date ? ts : new Date(ts);
if (Number.isNaN(date.getTime())) return;
const zone = resolveEnvelopeTimezone(resolved);
if (zone.mode !== "utc") return formatZonedTimestamp(date, {
timeZone: zone.mode === "iana" ? zone.timeZone : void 0,
displaySeconds: true,
displayWeekday: true
});
const formatted = formatUtcTimestamp(date, { displaySeconds: true });
try {
return `${new Intl.DateTimeFormat("en-US", {
timeZone: "UTC",
weekday: "short"
}).format(date)} ${formatted}`;
} catch {
return formatted;
}
}
function resolveDirectEnvelopeBodyLabel(from) {
const label = sanitizeEnvelopeHeaderPart(from || "");
const idMarkerIndex = label.search(/\s+id:/i);
if (idMarkerIndex > 0) {
const displayLabel = label.slice(0, idMarkerIndex).trim();
return displayLabel.includes(":") ? "(sender)" : displayLabel;
}
return label.includes(":") ? "(sender)" : label;
}
/** Formats the generic bracketed envelope prepended to agent-visible messages. */
function formatAgentEnvelope(params) {
const parts = [sanitizeEnvelopeHeaderPart(normalizeOptionalString(params.channel) || "Channel")];
const resolved = normalizeEnvelopeOptions(params.envelope);
let elapsed;
if (resolved.includeElapsed && params.timestamp && params.previousTimestamp) {
const elapsedMs = (params.timestamp instanceof Date ? params.timestamp.getTime() : params.timestamp) - (params.previousTimestamp instanceof Date ? params.previousTimestamp.getTime() : params.previousTimestamp);
elapsed = Number.isFinite(elapsedMs) && elapsedMs >= 0 ? formatTimeAgo(elapsedMs, { suffix: false }) : void 0;
}
const from = normalizeOptionalString(params.from);
if (from) {
const fromLabel = sanitizeEnvelopeHeaderPart(from);
parts.push(elapsed ? `${fromLabel} +${elapsed}` : fromLabel);
} else if (elapsed) parts.push(`+${elapsed}`);
const host = normalizeOptionalString(params.host);
if (host) parts.push(sanitizeEnvelopeHeaderPart(host));
const ip = normalizeOptionalString(params.ip);
if (ip) parts.push(sanitizeEnvelopeHeaderPart(ip));
const ts = formatAgentEnvelopeTimestamp(params.timestamp, resolved);
if (ts) parts.push(ts);
return `${`[${parts.join(" ")}]`} ${params.body}`;
}
/** Formats an inbound message body with sender attribution appropriate for direct/group chats. */
function formatInboundEnvelope(params) {
const chatType = normalizeChatType(params.chatType);
const isDirect = !chatType || chatType === "direct";
const resolvedSenderRaw = normalizeOptionalString(params.senderLabel) || resolveSenderLabel(params.sender ?? {});
const resolvedSender = resolvedSenderRaw ? sanitizeEnvelopeHeaderPart(resolvedSenderRaw) : "";
const directSender = resolveDirectEnvelopeBodyLabel(normalizeOptionalString(params.from));
const body = isDirect && params.fromMe ? `(self): ${params.body}` : isDirect && directSender ? `${directSender}: ${params.body}` : !isDirect && resolvedSender ? `${resolvedSender}: ${params.body}` : params.body;
return formatAgentEnvelope({
channel: params.channel,
from: params.from,
timestamp: params.timestamp,
previousTimestamp: params.previousTimestamp,
envelope: params.envelope,
body
});
}
/** Builds the compact `from` label used in inbound envelope headers. */
function formatInboundFromLabel(params) {
if (params.isGroup) {
const label = normalizeOptionalString(params.groupLabel) || params.groupFallback || "Group";
const id = params.groupId?.trim();
return id ? `${label} id:${id}` : label;
}
const directLabel = params.directLabel.trim();
const directId = params.directId?.trim();
if (!directId || directId === directLabel) return directLabel;
return `${directLabel} id:${directId}`;
}
//#endregion
export { resolveEnvelopeFormatOptions as a, formatInboundFromLabel as i, formatAgentEnvelopeTimestamp as n, formatInboundEnvelope as r, formatAgentEnvelope as t };