openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
143 lines (142 loc) • 5.34 kB
JavaScript
import { a as asNullableRecord } from "./runtime-doctor-migrations-DJDQaWC5.js";
import { c as hasLegacyAccountStreamingAliases, d as resolveLegacyAliasStreamingMode, l as hasLegacyStreamingAliases, t as materializeInheritedAccountStreaming, u as normalizeLegacyChannelAliases } from "./channel-doctor-helpers-CKvCIMDR.js";
//#region src/config/channel-alias-migration.ts
function buildAliasRuleMessage(params) {
const { streaming, prefix } = params;
const native = streaming.resolveNativeTransport !== void 0;
const flat = [
...streaming.deliveryOnly ? [] : ["streamMode", "streaming (scalar)"],
"chunkMode",
"blockStreaming",
...streaming.includePreviewChunk ? ["draftChunk"] : [],
"blockStreamingCoalesce",
...native ? ["nativeStreaming"] : []
];
const nested = [
...streaming.deliveryOnly ? [] : ["mode"],
"chunkMode",
...streaming.includePreviewChunk ? ["preview.chunk"] : [],
"block.enabled",
"block.coalesce",
...native ? ["nativeTransport"] : []
];
const prefixedCount = params.root && !streaming.deliveryOnly ? 2 : 1;
const keys = flat.map((key, index) => index < prefixedCount ? `${prefix}.${key}` : key);
return `${`${keys.slice(0, -1).join(", ")}, and ${keys.at(-1)}`} are legacy; use ${prefix}.streaming.{${nested.join(",")}}. Run "openclaw doctor --fix".`;
}
function hasLegacyDmAliases(value) {
const dm = asNullableRecord(asNullableRecord(value)?.dm);
return dm !== null && (Object.hasOwn(dm, "policy") || Object.hasOwn(dm, "allowFrom"));
}
/**
* Builds the standard channel doctor alias-migration surface from a small spec:
* detection rules (root + accounts), the per-entry matcher, and the config
* normalizer. Channels with additional migrations compose around these pieces.
*/
function defineChannelAliasMigration(spec) {
const { streaming } = spec;
const pathPrefix = `channels.${spec.channelId}`;
const hasLegacyAliases = (value) => {
if (streaming.deliveryOnly === true) {
const entry = asNullableRecord(value);
return entry !== null && (entry.chunkMode !== void 0 || entry.blockStreaming !== void 0 || entry.blockStreamingCoalesce !== void 0);
}
return hasLegacyStreamingAliases(value, {
includePreviewChunk: streaming.includePreviewChunk,
includeNativeTransport: streaming.resolveNativeTransport !== void 0
});
};
const resolveStreamingOptions = (entry) => ({
resolvedMode: streaming.resolveMode?.(entry) ?? resolveLegacyAliasStreamingMode(entry, streaming.defaultMode),
aliasOnlyMode: streaming.absentObjectDefault,
includePreviewChunk: streaming.includePreviewChunk,
resolvedNativeTransport: streaming.resolveNativeTransport?.(entry)
});
const normalizeChannelConfig = (params) => {
const changes = params.changes ?? [];
const channels = params.cfg.channels;
const entry = asNullableRecord(channels?.[spec.channelId]);
if (!entry) return {
config: params.cfg,
changes
};
const accountsBefore = spec.accountStreamingInheritsDefaultAccount ? asNullableRecord(entry.accounts) : null;
if (streaming.deliveryOnly === true && !hasLegacyAliases(entry) && !hasLegacyAccountStreamingAliases(entry.accounts, hasLegacyAliases) && !(spec.dm?.root && hasLegacyDmAliases(entry)) && !(spec.dm?.accounts && hasLegacyAccountStreamingAliases(entry.accounts, hasLegacyDmAliases))) return {
config: params.cfg,
changes
};
const result = normalizeLegacyChannelAliases({
entry,
pathPrefix,
changes,
normalizeDm: spec.dm?.root,
rootDmPromoteAllowFrom: spec.dm?.rootPromoteAllowFrom,
normalizeAccountDm: spec.dm?.accounts,
seedAccountStreamingFromRoot: spec.accountStreamingReplacesRoot,
resolveStreamingOptions,
normalizeAccountExtra: spec.normalizeAccountExtra
});
if (!result.changed) return {
config: params.cfg,
changes
};
const config = {
...params.cfg,
channels: {
...channels,
[spec.channelId]: result.entry
}
};
return {
config: spec.accountStreamingInheritsDefaultAccount ? materializeInheritedAccountStreaming({
cfg: config,
channelId: spec.channelId,
accountsBefore,
changes
}) : config,
changes
};
};
const legacyConfigRules = [{
path: ["channels", spec.channelId],
message: buildAliasRuleMessage({
streaming,
prefix: pathPrefix,
root: true
}),
match: hasLegacyAliases
}, {
path: [
"channels",
spec.channelId,
"accounts"
],
message: buildAliasRuleMessage({
streaming,
prefix: `${pathPrefix}.accounts.<id>`,
root: false
}),
match: (value) => hasLegacyAccountStreamingAliases(value, hasLegacyAliases)
}];
if (spec.dm?.root) legacyConfigRules.push({
path: ["channels", spec.channelId],
message: `${pathPrefix}.dm.policy and ${pathPrefix}.dm.allowFrom are legacy; use ${pathPrefix}.dmPolicy and ${pathPrefix}.allowFrom. Run "openclaw doctor --fix".`,
match: hasLegacyDmAliases
});
if (spec.dm?.accounts) legacyConfigRules.push({
path: [
"channels",
spec.channelId,
"accounts"
],
message: `${pathPrefix}.accounts.<id>.dm.policy and dm.allowFrom are legacy; use ${pathPrefix}.accounts.<id>.dmPolicy and allowFrom. Run "openclaw doctor --fix".`,
match: (value) => hasLegacyAccountStreamingAliases(value, hasLegacyDmAliases)
});
return {
legacyConfigRules,
hasLegacyAliases,
normalizeChannelConfig
};
}
//#endregion
export { defineChannelAliasMigration as t };