// agent = openclaw channel account. // Config shape: // channels.fabric.centerApiBase = "http://localhost:7001/api" (shared) // channels.fabric.accounts. = { fabricApiKey, centerApiBase? } // Each account id IS the openclaw agentId that owns that Fabric identity. const DEFAULT_CENTER = 'http://localhost:7001/api'; function section(cfg) { return cfg.channels?.fabric ?? {}; } // The commands-sync shared secret (channel-level only). Empty string when // unconfigured — callers decide how to handle (slash-command sync is then // rejected by the guild). export function resolveCommandsSyncKey(cfg) { return (section(cfg).commandsSyncKey ?? '').trim(); } // Whether to coalesce a split agent turn into one Fabric message // (channel-level). Default true. export function resolveCoalesce(cfg) { return (cfg.channels?.fabric ?? {}).coalesce !== false; } export function listFabricAccountIds(cfg) { const accts = section(cfg).accounts ?? {}; const ids = Object.keys(accts); return ids.length ? ids : ['default']; } export function resolveDefaultFabricAccountId(cfg) { const s = section(cfg); if (s.defaultAccount) return s.defaultAccount; const ids = listFabricAccountIds(cfg); return ids[0] ?? 'default'; } export function resolveFabricAccount(cfg, accountId) { const s = section(cfg); const id = accountId ?? resolveDefaultFabricAccountId(cfg); const acc = s.accounts?.[id] ?? {}; const fabricApiKey = (acc.fabricApiKey ?? '').trim(); const centerApiBase = (acc.centerApiBase ?? s.centerApiBase ?? DEFAULT_CENTER).trim(); return { accountId: id, enabled: acc.enabled !== false && s.enabled !== false, centerApiBase, fabricApiKey, allowFrom: acc.allowFrom ?? s.allowFrom ?? [], dmPolicy: acc.dmPolicy ?? s.dmPolicy, }; } export function listEnabledFabricAccounts(cfg) { return listFabricAccountIds(cfg) .map((id) => resolveFabricAccount(cfg, id)) .filter((a) => a.enabled && a.fabricApiKey); }