import fs from "node:fs"; import path from "node:path"; import { fileURLToPath } from "node:url"; import { listChannelPluginCatalogEntries } from "../channels/plugins/catalog.js"; import { listChannelPlugins } from "../channels/plugins/index.js"; import { CHAT_CHANNEL_ORDER } from "../channels/registry.js"; import { isTruthyEnvValue } from "../infra/env.js"; import { ensurePluginRegistryLoaded } from "./plugin-registry.js"; function dedupe(values: string[]): string[] { const seen = new Set(); const resolved: string[] = []; for (const value of values) { if (!value || seen.has(value)) { continue; } seen.add(value); resolved.push(value); } return resolved; } let precomputedChannelOptions: string[] | null | undefined; function loadPrecomputedChannelOptions(): string[] | null { if (precomputedChannelOptions !== undefined) { return precomputedChannelOptions; } try { const metadataPath = path.resolve( path.dirname(fileURLToPath(import.meta.url)), "..", "cli-startup-metadata.json", ); const raw = fs.readFileSync(metadataPath, "utf8"); const parsed = JSON.parse(raw) as { channelOptions?: unknown }; if (Array.isArray(parsed.channelOptions)) { precomputedChannelOptions = dedupe( parsed.channelOptions.filter((value): value is string => typeof value === "string"), ); return precomputedChannelOptions; } } catch { // Fall back to dynamic catalog resolution. } precomputedChannelOptions = null; return null; } export function resolveCliChannelOptions(): string[] { if (isTruthyEnvValue(process.env.OPENCLAW_EAGER_CHANNEL_OPTIONS)) { const catalog = listChannelPluginCatalogEntries().map((entry) => entry.id); const base = dedupe([...CHAT_CHANNEL_ORDER, ...catalog]); ensurePluginRegistryLoaded(); const pluginIds = listChannelPlugins().map((plugin) => plugin.id); return dedupe([...base, ...pluginIds]); } const precomputed = loadPrecomputedChannelOptions(); const catalog = listChannelPluginCatalogEntries().map((entry) => entry.id); const base = precomputed ? dedupe([...precomputed, ...catalog]) : dedupe([...CHAT_CHANNEL_ORDER, ...catalog]); return base; } export function formatCliChannelOptions(extra: string[] = []): string { return [...extra, ...resolveCliChannelOptions()].join("|"); }