openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
69 lines (68 loc) • 3.54 kB
JavaScript
import { o as asNullableRecord } from "./string-coerce-6O-WySZM.js";
import { u as normalizeChannelConfigEntries } from "./runtime-doctor-migrations-BdgZ9Dfo.js";
//#region src/plugin-sdk/legacy-webhook-listener-migration.ts
/** Preserve explicitly configured webhook listeners while moving ingress onto Gateway routes. */
function createLegacyWebhookListenerDoctorContract(params) {
const portKey = params.portKey ?? "webhookPort";
const hostKey = params.hostKey === void 0 ? "webhookHost" : params.hostKey;
const source = (entry) => params.webhookKey ? asNullableRecord(entry[params.webhookKey]) : entry;
const hasLegacy = (value) => {
const entry = asNullableRecord(value);
const listener = entry && source(entry);
return Boolean(listener && (Object.hasOwn(listener, portKey) || hostKey && Object.hasOwn(listener, hostKey)));
};
const prefix = `channels.${params.channelKey}`;
return {
legacyConfigRules: [{
path: ["channels", params.channelKey],
message: `${prefix} webhook listeners moved to Gateway routes. Run "openclaw doctor --fix" to preserve explicitly configured listener settings as legacyWebhook.`,
match: (value) => {
const accounts = asNullableRecord(asNullableRecord(value)?.accounts);
return hasLegacy(value) || Object.values(accounts ?? {}).some(hasLegacy);
}
}],
normalizeCompatibilityConfig: ({ cfg }) => {
const root = asNullableRecord(asNullableRecord(cfg.channels)?.[params.channelKey]);
const inherited = root && source(root);
const canonicalRoot = asNullableRecord(root?.legacyWebhook);
return normalizeChannelConfigEntries({
cfg,
channelId: params.channelKey,
normalizeEntry: ({ entry, accountId, pathPrefix, changes }) => {
const listener = source(entry);
if (!listener || !hasLegacy(entry)) return {
entry,
changed: false
};
const next = { ...entry };
const port = Object.hasOwn(listener, portKey) ? listener[portKey] : (accountId ? canonicalRoot?.port ?? inherited?.[portKey] : void 0) ?? params.defaultPort;
const inheritedHost = accountId ? canonicalRoot ? canonicalRoot.host : (hostKey ? inherited?.[hostKey] : void 0) ?? params.defaultHost : params.defaultHost;
const host = hostKey ? listener[hostKey] ?? inheritedHost : inheritedHost;
const legacyPath = [pathPrefix, params.webhookKey].filter(Boolean).join(".");
if (Object.hasOwn(entry, "legacyWebhook")) changes.push(`Removed ${legacyPath} legacy listener keys; ${pathPrefix}.legacyWebhook is already configured.`);
else if (accountId && root?.legacyWebhook === false) changes.push(`Removed ${legacyPath} legacy listener keys; ${prefix}.legacyWebhook: false keeps this account's inherited listener disabled.`);
else {
next.legacyWebhook = {
port,
...host !== void 0 ? { host } : {}
};
changes.push(`Moved ${legacyPath} listener settings to ${pathPrefix}.legacyWebhook. Point the external callback or reverse proxy at the Gateway port and webhook path, verify delivery, then set legacyWebhook: false to disable legacy forwarding.`);
}
const updated = params.webhookKey ? { ...listener } : next;
delete updated[portKey];
if (hostKey) delete updated[hostKey];
if (params.webhookKey) {
if (Object.keys(updated).length) next[params.webhookKey] = updated;
else delete next[params.webhookKey];
}
return {
entry: next,
changed: true
};
}
});
}
};
}
//#endregion
export { createLegacyWebhookListenerDoctorContract as t };