export const OPENCLAW_CHAT_CONFIG_KEY = "openclaw_chat_config"; export const DEFAULT_OPENCLAW_CHAT_BASE_URL = "http://192.168.42.154:18790"; export type OpenClawChatConfig = { enabled: boolean; baseUrl: string; token: string; timeoutMs: number; }; export type PublicOpenClawChatConfig = { enabled: boolean; baseUrl: string; }; export type AdminOpenClawChatConfig = Omit & { token: ""; hasToken: boolean; tokenPreview: string; }; const DEFAULT_TIMEOUT_MS = 180_000; const MIN_TIMEOUT_MS = 5_000; const MAX_TIMEOUT_MS = 300_000; function readRecord(value: unknown): Record { return value && typeof value === "object" && !Array.isArray(value) ? (value as Record) : {}; } function normalizeBaseUrl(value: unknown) { return ( String(value || "").trim().replace(/\/+$/, "") || DEFAULT_OPENCLAW_CHAT_BASE_URL ); } function normalizeTimeoutMs(value: unknown) { const numeric = Number(value); if (!Number.isFinite(numeric)) return DEFAULT_TIMEOUT_MS; return Math.min(MAX_TIMEOUT_MS, Math.max(MIN_TIMEOUT_MS, Math.round(numeric))); } export function normalizeOpenClawChatConfig( value: unknown, fallbackToken = "" ): OpenClawChatConfig { const raw = readRecord(value); const token = String(raw.token || "").trim() || fallbackToken.trim(); return { enabled: raw.enabled === true, baseUrl: normalizeBaseUrl(raw.baseUrl), token, timeoutMs: normalizeTimeoutMs(raw.timeoutMs), }; } export function normalizePublicOpenClawChatConfig( value: unknown ): PublicOpenClawChatConfig { const config = normalizeOpenClawChatConfig(value); return { enabled: config.enabled && Boolean(config.baseUrl) && Boolean(config.token), baseUrl: config.baseUrl, }; } export function maskOpenClawToken(token: string) { const normalized = token.trim(); if (!normalized) return ""; if (normalized.length <= 8) return "********"; return `${normalized.slice(0, 4)}****${normalized.slice(-4)}`; } export function toAdminOpenClawChatConfig( value: unknown ): AdminOpenClawChatConfig { const config = normalizeOpenClawChatConfig(value); return { enabled: config.enabled, baseUrl: config.baseUrl, token: "", hasToken: Boolean(config.token), tokenPreview: maskOpenClawToken(config.token), timeoutMs: config.timeoutMs, }; }