openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
182 lines (181 loc) • 9.72 kB
JavaScript
import { l as normalizeOptionalString } from "./string-coerce-1VuiLaaR.mjs";
import { p as normalizeTrimmedStringList } from "./string-normalization-CECOqf64.mjs";
import { u as tryReadJsonSync } from "./json-files-C5mNTScg.mjs";
import { r as getPackageManifestMetadata, s as pluginCacheExistsSync } from "./package-manifest-CEbdS_C4.mjs";
import { t as PUBLIC_SURFACE_SOURCE_EXTENSIONS } from "./package-entrypoints-DCjwjOnD.mjs";
import { r as loadPluginManifest } from "./manifest-BXjFCp0F.mjs";
import { t as getCachedPluginModuleLoader } from "./plugin-module-loader-cache-CUtYxPiw.mjs";
import { s as resolveLoaderPackageRoot } from "./sdk-alias-A9rXLURS.mjs";
import { a as resolveBundledPluginScanDir, n as collectBundledPluginRuntimeSidecarArtifacts, o as rewriteBundledPluginEntryToBuiltPath, r as deriveBundledPluginIdHint, t as collectBundledPluginPublicSurfaceArtifacts } from "./bundled-plugin-scan-BmpR7Vr3.mjs";
import { i as buildChannelConfigSchema, o as buildJsonChannelConfigSchema } from "./config-schema-Be-FohaC.mjs";
import fs from "node:fs";
import { fileURLToPath } from "node:url";
import path from "node:path";
//#region src/plugins/bundled-channel-config-metadata.ts
/** Loads bundled channel config schema metadata from source or public surface modules. */
const SOURCE_CONFIG_SCHEMA_CANDIDATES = [
path.join("src", "config-schema.ts"),
path.join("src", "config-schema.js"),
path.join("src", "config-schema.mts"),
path.join("src", "config-schema.mjs"),
path.join("src", "config-schema.cts"),
path.join("src", "config-schema.cjs")
];
function isBuiltChannelConfigSchema(value) {
if (!value || typeof value !== "object") return false;
const candidate = value;
return Boolean(candidate.schema && typeof candidate.schema === "object");
}
function isJsonSchemaConfigSurface(value) {
if (!value || typeof value !== "object") return false;
const candidate = value;
if (typeof candidate.safeParse === "function" || typeof candidate.toJSONSchema === "function") return false;
return typeof candidate.type === "string" || Array.isArray(candidate.anyOf) || Array.isArray(candidate.oneOf) || Array.isArray(candidate.allOf) || Array.isArray(candidate.enum) || Object.hasOwn(candidate, "const");
}
function resolveConfigSchemaExport(imported) {
for (const [name, value] of Object.entries(imported)) if (name.endsWith("ChannelConfigSchema") && isBuiltChannelConfigSchema(value)) return value;
for (const [name, value] of Object.entries(imported)) {
if (!name.endsWith("ConfigSchema") || name.endsWith("AccountConfigSchema")) continue;
if (isBuiltChannelConfigSchema(value)) return value;
if (isJsonSchemaConfigSurface(value)) return buildJsonChannelConfigSchema(value);
if (value && typeof value === "object") return buildChannelConfigSchema(value);
}
return Object.values(imported).find(isBuiltChannelConfigSchema) ?? null;
}
function resolveChannelConfigSchemaModulePath(pluginDir) {
for (const relativePath of SOURCE_CONFIG_SCHEMA_CANDIDATES) {
const candidate = path.join(pluginDir, relativePath);
if (pluginCacheExistsSync(candidate)) return candidate;
}
for (const extension of PUBLIC_SURFACE_SOURCE_EXTENSIONS) {
const candidate = path.join(pluginDir, `channel-config-api${extension}`);
if (pluginCacheExistsSync(candidate)) return candidate;
}
}
function loadChannelConfigSurfaceModuleSync(modulePath) {
try {
return resolveConfigSchemaExport(getCachedPluginModuleLoader({
modulePath,
importerUrl: import.meta.url,
preferBuiltDist: true,
loaderFilename: import.meta.url
})(modulePath));
} catch {
return null;
}
}
function resolvePackageChannelMeta(packageManifest, channelId) {
const channelMeta = packageManifest?.channel;
return channelMeta?.id?.trim() === channelId ? channelMeta : void 0;
}
function collectBundledChannelConfigsCore(params) {
const channelIds = normalizeTrimmedStringList(params.manifest.channels);
const existingChannelConfigs = params.manifest.channelConfigs && Object.keys(params.manifest.channelConfigs).length > 0 ? { ...params.manifest.channelConfigs } : {};
if (channelIds.length === 0) return Object.keys(existingChannelConfigs).length > 0 ? existingChannelConfigs : void 0;
const surfaceModulePath = resolveChannelConfigSchemaModulePath(params.pluginDir);
const surface = surfaceModulePath ? loadChannelConfigSurfaceModuleSync(surfaceModulePath) : null;
for (const channelId of channelIds) {
const existing = existingChannelConfigs[channelId];
const channelMeta = resolvePackageChannelMeta(params.packageManifest, channelId);
const preferOver = normalizeTrimmedStringList(channelMeta?.preferOver);
const uiHints = {
...surface?.uiHints,
...existing?.uiHints
};
if (!surface?.schema && !existing?.schema) continue;
const runtime = surface?.runtime ?? existing?.runtime;
const label = normalizeOptionalString(existing?.label) ?? normalizeOptionalString(channelMeta?.label);
const description = normalizeOptionalString(existing?.description) ?? normalizeOptionalString(channelMeta?.blurb);
const commands = existing?.commands ?? channelMeta?.commands;
existingChannelConfigs[channelId] = {
schema: surface?.schema ?? existing?.schema ?? {},
...Object.keys(uiHints).length > 0 ? { uiHints } : {},
...runtime ? { runtime } : {},
...label ? { label } : {},
...description ? { description } : {},
...existing?.preferOver?.length ? { preferOver: existing.preferOver } : preferOver.length > 0 ? { preferOver } : {},
...commands ? { commands } : {}
};
}
return Object.keys(existingChannelConfigs).length > 0 ? existingChannelConfigs : void 0;
}
//#endregion
//#region src/plugins/bundled-plugin-metadata.ts
const OPENCLAW_PACKAGE_ROOT = resolveLoaderPackageRoot({
modulePath: fileURLToPath(import.meta.url),
moduleUrl: import.meta.url
}) ?? fileURLToPath(new URL("../..", import.meta.url));
const CURRENT_MODULE_PATH = fileURLToPath(import.meta.url);
const RUNNING_FROM_BUILT_ARTIFACT = CURRENT_MODULE_PATH.includes(`${path.sep}dist${path.sep}`) || CURRENT_MODULE_PATH.includes(`${path.sep}dist-runtime${path.sep}`);
/** Lists bundled plugin metadata from source or built package layouts. */
function listBundledPluginMetadata(params) {
const rootDir = path.resolve(params?.rootDir ?? OPENCLAW_PACKAGE_ROOT);
const resolvedScanDir = params?.scanDir ? path.resolve(params.scanDir) : resolveBundledPluginScanDir({
packageRoot: rootDir,
runningFromBuiltArtifact: RUNNING_FROM_BUILT_ARTIFACT
});
const includeChannelConfigs = params?.includeChannelConfigs ?? !RUNNING_FROM_BUILT_ARTIFACT;
const includeSyntheticChannelConfigs = params?.includeSyntheticChannelConfigs ?? includeChannelConfigs;
if (!resolvedScanDir || !fs.existsSync(resolvedScanDir)) return Object.freeze([]);
const entries = [];
for (const dirName of fs.readdirSync(resolvedScanDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).toSorted((left, right) => left.localeCompare(right))) {
const pluginDir = path.join(resolvedScanDir, dirName);
const manifestResult = loadPluginManifest(pluginDir, false);
if (!manifestResult.ok) continue;
const packageJson = tryReadJsonSync(path.join(pluginDir, "package.json")) ?? void 0;
const packageManifest = getPackageManifestMetadata(packageJson);
const extensions = normalizeTrimmedStringList(packageManifest?.extensions);
if (extensions.length === 0) continue;
const sourceEntry = extensions[0];
const builtEntry = rewriteBundledPluginEntryToBuiltPath(sourceEntry);
if (!sourceEntry || !builtEntry) continue;
const setupSourcePath = normalizeOptionalString(packageManifest?.setupEntry);
const setupBuiltPath = rewriteBundledPluginEntryToBuiltPath(setupSourcePath);
const setupSource = setupSourcePath && setupBuiltPath ? {
source: setupSourcePath,
built: setupBuiltPath
} : void 0;
const publicSurfaceArtifacts = collectBundledPluginPublicSurfaceArtifacts({
pluginDir,
sourceEntry,
...setupSourcePath ? { setupEntry: setupSourcePath } : {}
});
const runtimeSidecarArtifacts = collectBundledPluginRuntimeSidecarArtifacts(publicSurfaceArtifacts);
const channelConfigs = includeChannelConfigs && includeSyntheticChannelConfigs ? collectBundledChannelConfigsCore({
pluginDir,
manifest: manifestResult.manifest,
packageManifest
}) : manifestResult.manifest.channelConfigs;
entries.push({
dirName,
idHint: deriveBundledPluginIdHint({
entryPath: sourceEntry,
manifestId: manifestResult.manifest.id,
packageName: normalizeOptionalString(packageJson?.name),
hasMultipleExtensions: extensions.length > 1
}),
source: {
source: sourceEntry,
built: builtEntry
},
...setupSource ? { setupSource } : {},
...publicSurfaceArtifacts ? { publicSurfaceArtifacts } : {},
...runtimeSidecarArtifacts ? { runtimeSidecarArtifacts } : {},
...normalizeOptionalString(packageJson?.name) ? { packageName: normalizeOptionalString(packageJson?.name) } : {},
...normalizeOptionalString(packageJson?.version) ? { packageVersion: normalizeOptionalString(packageJson?.version) } : {},
...normalizeOptionalString(packageJson?.description) ? { packageDescription: normalizeOptionalString(packageJson?.description) } : {},
...packageManifest ? { packageManifest } : {},
manifest: {
...manifestResult.manifest,
...channelConfigs ? { channelConfigs } : {}
}
});
}
return Object.freeze(entries);
}
/** Finds bundled plugin metadata by manifest id. */
function findBundledPluginMetadataById(pluginId, params) {
return listBundledPluginMetadata(params).find((entry) => entry.manifest.id === pluginId);
}
//#endregion
export { listBundledPluginMetadata as n, findBundledPluginMetadataById as t };