openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
301 lines (300 loc) • 17.1 kB
JavaScript
import { i as resolveGlobalSingleton } from "./global-singleton-Dc_stLtU.js";
import { c as getPluginMetadataSnapshotCache, f as withPluginCache, l as getProcessPluginCache, t as adoptProcessPluginCache, u as getScopedPluginCache } from "./plugin-cache-DGWspMEc.js";
import { d as normalizeStringEntries } from "./string-normalization-DsCfAx8q.js";
import { n as tryProcessCwd } from "./safe-cwd-DOxDm8mD.js";
import { i as getGatewayPluginMetadataSnapshot, n as currentPluginMetadataConfigIdentityCache, r as getCurrentPluginMetadataSnapshotState, s as setCurrentPluginMetadataSnapshotState } from "./current-plugin-metadata-state-B1UoAr4G.js";
import { o as shouldTrustTestBundledPluginsDirOverride } from "./bundled-dir-BEfbEeCF.js";
import { n as resolveActivePluginInstallRoots, t as hasActivePluginInstallRoots } from "./install-root-context-BSQp2WLR.js";
import { _ as resolveInstalledPluginIndexPolicyHash } from "./installed-plugin-index-wrDsjyMD.js";
import { S as hashJson } from "./discovery-D_VDsZuY.js";
import { t as resolvePluginCacheInputs } from "./roots-BBmaCv0d.js";
import { n as resolveInstalledManifestRegistryIndexFingerprint } from "./manifest-registry-installed-DdhpzefH.js";
import { r as registerPluginMetadataSnapshotReaders } from "./plugin-metadata-snapshot.runtime.js";
import { AsyncLocalStorage } from "node:async_hooks";
//#region src/plugins/plugin-control-plane-context.ts
function resolveConfiguredPluginLoadPaths(config) {
const paths = config?.plugins?.load?.paths;
return Array.isArray(paths) ? paths : void 0;
}
/** Resolves plugin discovery roots and load paths for cache/fingerprint callers. */
function resolvePluginDiscoveryContext(params = {}) {
return resolvePluginCacheInputs({
env: params.env ?? process.env,
workspaceDir: params.workspaceDir,
loadPaths: [...params.loadPaths ?? resolveConfiguredPluginLoadPaths(params.config) ?? []]
});
}
/** Hashes an already resolved plugin discovery context. */
function fingerprintPluginDiscoveryContext(context) {
return hashJson(context);
}
/** Resolves all inputs that determine plugin control-plane activation state. */
function resolvePluginControlPlaneContext(params = {}) {
const inventoryFingerprint = params.inventoryFingerprint ?? (params.index ? resolveInstalledManifestRegistryIndexFingerprint(params.index) : void 0);
return {
discovery: resolvePluginDiscoveryContext(params),
policyFingerprint: params.policyHash ?? resolveInstalledPluginIndexPolicyHash(params.config, params.env),
...inventoryFingerprint ? { inventoryFingerprint } : {},
...params.activationFingerprint ? { activationFingerprint: params.activationFingerprint } : {}
};
}
/** Resolves a stable fingerprint for plugin control-plane activation state. */
function resolvePluginControlPlaneFingerprint(params = {}) {
return fingerprintPluginControlPlaneContext(resolvePluginControlPlaneContext(params));
}
function fingerprintPluginControlPlaneContext(context) {
return hashJson(context);
}
//#endregion
//#region src/plugins/plugin-metadata-env.ts
const PLUGIN_METADATA_ENV_KEYS = [
"ANDROID_DATA",
"APPDATA",
"HOME",
"OPENCLAW_BUNDLED_PLUGINS_DIR",
"OPENCLAW_COMPATIBILITY_HOST_VERSION",
"OPENCLAW_CONFIG_PATH",
"OPENCLAW_DEV_SOURCE_ROOT",
"OPENCLAW_DISABLE_BUNDLED_PLUGINS",
"OPENCLAW_DISABLE_BUNDLED_SOURCE_OVERLAYS",
"OPENCLAW_HOME",
"OPENCLAW_NIX_MODE",
"OPENCLAW_STATE_DIR",
"PREFIX",
"USERPROFILE",
"XDG_CONFIG_HOME"
];
/** Compares discovery namespaces without resolving or probing filesystem roots. */
function resolvePluginMetadataEnvFingerprint(env = process.env) {
return hashJson({
env: Object.fromEntries(PLUGIN_METADATA_ENV_KEYS.flatMap((key) => {
const value = env[key];
return value === void 0 ? [] : [[key, value]];
})),
installRoots: hasActivePluginInstallRoots() ? resolveActivePluginInstallRoots() : void 0,
trustBundledPluginsDirOverride: shouldTrustTestBundledPluginsDirOverride(env),
cwd: tryProcessCwd()
});
}
//#endregion
//#region src/plugins/plugin-scope.ts
/** Normalizes plugin id scope input into a sorted unique string list. */
function normalizePluginIdScope(ids) {
if (ids === void 0) return;
return Array.from(new Set(normalizeStringEntries(ids.filter((id) => typeof id === "string")))).toSorted();
}
/** True when plugin scope was explicitly provided, including an empty scope. */
function hasExplicitPluginIdScope(ids) {
return ids !== void 0;
}
/** True when plugin scope was explicitly provided with at least one id. */
function hasNonEmptyPluginIdScope(ids) {
return ids !== void 0 && ids.length > 0;
}
/** Creates a lookup set for explicit plugin scope, or null when unscoped. */
function createPluginIdScopeSet(ids) {
if (ids === void 0) return null;
return new Set(ids);
}
/** Serializes plugin scope for cache keys. */
function serializePluginIdScope(ids) {
return ids === void 0 ? "__unscoped__" : JSON.stringify(ids);
}
//#endregion
//#region src/plugins/current-plugin-metadata-snapshot.ts
/** Tracks the current plugin metadata snapshot for control-plane lookups. */
let activeTemporaryPluginMetadataSnapshotLease;
const scopedPluginMetadataSnapshot = resolveGlobalSingleton(Symbol.for("openclaw.scopedPluginMetadataSnapshot"), () => new AsyncLocalStorage());
function resolvePluginMetadataControlPlaneFingerprint(config, options = {}) {
return resolvePluginControlPlaneFingerprint({
config,
...options
});
}
function publishCurrentPluginMetadataSnapshot(snapshot, options, owner = "operation") {
if (getCurrentPluginMetadataSnapshotState().owner === "gateway") throw new Error("Gateway plugin metadata can only be replaced after shutdown");
currentPluginMetadataConfigIdentityCache.clear();
const fingerprint = (config, policyHash) => resolvePluginMetadataControlPlaneFingerprint(config, {
env: options.env,
index: snapshot.index,
policyHash,
workspaceDir: options.workspaceDir ?? snapshot.workspaceDir
});
const compatiblePolicyHashes = options.compatibleConfigs?.map((config) => resolveInstalledPluginIndexPolicyHash(config, options.env));
const compatibleConfigFingerprints = options.compatibleConfigs?.map((config, index) => fingerprint(config, compatiblePolicyHashes?.[index]));
const configFingerprint = fingerprint(options.config, snapshot.policyHash);
const defaultDiscoveryConfigFingerprint = fingerprint({}, snapshot.policyHash);
const defaultDiscoveryCompatible = configFingerprint === defaultDiscoveryConfigFingerprint || snapshot.configFingerprint === defaultDiscoveryConfigFingerprint || Boolean(compatibleConfigFingerprints?.includes(defaultDiscoveryConfigFingerprint));
const revision = setCurrentPluginMetadataSnapshotState(snapshot, configFingerprint, compatiblePolicyHashes, compatibleConfigFingerprints, owner === "gateway" || defaultDiscoveryCompatible ? snapshot.owners.modelIdNormalizationPolicies : void 0, owner, resolvePluginMetadataEnvFingerprint(options.env), defaultDiscoveryCompatible);
if (options.config) {
const policyHash = resolveInstalledPluginIndexPolicyHash(options.config, options.env);
if (policyHash === snapshot.policyHash || Boolean(compatiblePolicyHashes?.includes(policyHash))) currentPluginMetadataConfigIdentityCache.add(options.config);
}
for (const config of options.compatibleConfigs ?? []) currentPluginMetadataConfigIdentityCache.add(config);
return revision;
}
/** Publishes package facts once; config reload only replaces their runtime bindings. */
function setGatewayPluginMetadataSnapshot(snapshot, options = {}) {
if (!snapshot) return;
if (snapshot.pluginIds !== void 0) throw new Error("Gateway plugin metadata must include the complete startup inventory");
if (getCurrentPluginMetadataSnapshotState().owner === "gateway") throw new Error("Gateway plugin metadata can only be replaced after shutdown");
adoptProcessPluginCache(getPluginMetadataSnapshotCache(snapshot));
activeTemporaryPluginMetadataSnapshotLease = void 0;
publishCurrentPluginMetadataSnapshot(snapshot, options, "gateway");
}
/** Publishes a prepared CLI snapshot without displacing a lifecycle owner. */
function adoptCurrentPluginMetadataSnapshotIfAbsent(snapshot, options = {}) {
if (getScopedPluginCache()?.kind === "operation" || getCurrentPluginMetadataSnapshotState().snapshot !== void 0) return;
activeTemporaryPluginMetadataSnapshotLease = void 0;
publishCurrentPluginMetadataSnapshot(snapshot, options);
}
function isScopedSnapshotInCurrentCache(scoped) {
const cache = getScopedPluginCache();
return cache?.kind !== "operation" || !scoped.snapshot || getPluginMetadataSnapshotCache(scoped.snapshot) === cache;
}
function captureCurrentPluginMetadataSnapshotState() {
return {
...getCurrentPluginMetadataSnapshotState(),
configIdentities: currentPluginMetadataConfigIdentityCache.capture()
};
}
function restoreCapturedCurrentPluginMetadataSnapshotState(state) {
currentPluginMetadataConfigIdentityCache.restore(state.configIdentities);
return setCurrentPluginMetadataSnapshotState(state.snapshot, state.configFingerprint, state.compatiblePolicyHashes, state.compatibleConfigFingerprints, state.modelIdNormalizationPolicies, state.owner, state.envFingerprint, state.defaultDiscoveryCompatible);
}
function resolveTemporaryPluginMetadataSnapshotLeaseParent() {
const active = activeTemporaryPluginMetadataSnapshotLease;
if (active && getCurrentPluginMetadataSnapshotState().revision !== active.revision) {
activeTemporaryPluginMetadataSnapshotLease = void 0;
return;
}
return active;
}
function releaseTemporaryPluginMetadataSnapshotLease(lease) {
if (lease.released) return false;
lease.released = true;
if (activeTemporaryPluginMetadataSnapshotLease !== lease) return false;
let restored = false;
while (activeTemporaryPluginMetadataSnapshotLease?.released) {
const current = activeTemporaryPluginMetadataSnapshotLease;
if (getCurrentPluginMetadataSnapshotState().revision !== current.revision) {
activeTemporaryPluginMetadataSnapshotLease = void 0;
return restored;
}
const restoredRevision = restoreCapturedCurrentPluginMetadataSnapshotState(current.previousState);
activeTemporaryPluginMetadataSnapshotLease = current.parent;
if (activeTemporaryPluginMetadataSnapshotLease) activeTemporaryPluginMetadataSnapshotLease.revision = restoredRevision;
restored = true;
}
return restored;
}
/** Temporarily publishes metadata without restoring over lifecycle-owned replacements. */
function installTemporaryCurrentPluginMetadataSnapshot(snapshot, options = {}) {
const lease = {
parent: resolveTemporaryPluginMetadataSnapshotLeaseParent(),
previousState: captureCurrentPluginMetadataSnapshotState(),
revision: publishCurrentPluginMetadataSnapshot(snapshot, options),
released: false
};
activeTemporaryPluginMetadataSnapshotLease = lease;
return { release: () => releaseTemporaryPluginMetadataSnapshotLease(lease) };
}
/** Carries one owner-prepared metadata generation through nested async plugin lookups. */
function withPluginMetadataSnapshotScope(snapshot, run, options = {}) {
const workspaceDir = options.workspaceDir ?? snapshot.workspaceDir;
const compatiblePolicyHashes = options.compatibleConfigs?.map((config) => resolveInstalledPluginIndexPolicyHash(config, options.env));
const compatibleConfigFingerprints = options.compatibleConfigs?.map((config, index) => resolvePluginMetadataControlPlaneFingerprint(config, {
env: options.env,
index: snapshot.index,
policyHash: compatiblePolicyHashes?.[index],
workspaceDir
}));
const configFingerprint = options.config ? resolvePluginMetadataControlPlaneFingerprint(options.config, {
env: options.env,
index: snapshot.index,
policyHash: snapshot.policyHash,
workspaceDir
}) : snapshot.configFingerprint;
const configIdentities = /* @__PURE__ */ new WeakSet();
if (options.config) {
const policyHash = resolveInstalledPluginIndexPolicyHash(options.config, options.env);
if (options.trustConfigIdentity === true || policyHash === snapshot.policyHash || compatiblePolicyHashes?.includes(policyHash)) configIdentities.add(options.config);
}
for (const config of options.compatibleConfigs ?? []) configIdentities.add(config);
return withPluginCache(getPluginMetadataSnapshotCache(snapshot), () => scopedPluginMetadataSnapshot.run({
snapshot,
configFingerprint,
envFingerprint: resolvePluginMetadataEnvFingerprint(options.env),
compatiblePolicyHashes,
compatibleConfigFingerprints,
hasConfigIdentity: (config) => configIdentities.has(config),
immutableRuntimeGeneration: options.trustConfigIdentity === true,
parent: scopedPluginMetadataSnapshot.getStore()
}, run));
}
function resolveCompatiblePluginMetadataSnapshot(candidate, params, options = {}) {
const snapshot = candidate.snapshot;
if (!snapshot) return;
if (candidate.immutableRuntimeGeneration) return snapshot;
const env = params.env ?? process.env;
if (candidate.envFingerprint !== resolvePluginMetadataEnvFingerprint(env)) return;
const requestedPluginIds = normalizePluginIdScope(params.pluginIds ?? params.pluginIdScope?.resolve({ index: snapshot.index }));
const snapshotPluginIds = normalizePluginIdScope(snapshot.pluginIds);
if (requestedPluginIds !== void 0 && serializePluginIdScope(snapshotPluginIds) !== serializePluginIdScope(requestedPluginIds)) return;
if (snapshotPluginIds !== void 0 && requestedPluginIds === void 0 && params.allowScopedSnapshot !== true) return;
const requestedWorkspaceDir = params.workspaceDir ?? (params.allowWorkspaceScopedSnapshot === true || options.scopedOwnerContext === true ? snapshot.workspaceDir : void 0);
if (snapshot.workspaceDir !== void 0 && requestedWorkspaceDir === void 0) return;
if (requestedWorkspaceDir !== void 0 && (snapshot.workspaceDir ?? "") !== (requestedWorkspaceDir ?? "")) return;
const canReuseCachedConfig = Boolean(params.config && candidate.hasConfigIdentity?.(params.config));
if (canReuseCachedConfig && params.requireDefaultDiscoveryContext !== true) return snapshot;
const requestedPolicyHash = params.config && !canReuseCachedConfig ? resolveInstalledPluginIndexPolicyHash(params.config, params.env) : void 0;
if (requestedPolicyHash && snapshot.policyHash !== requestedPolicyHash) {
if (!candidate.compatiblePolicyHashes?.includes(requestedPolicyHash)) return;
}
if (params.config && !canReuseCachedConfig) {
const requestedConfigFingerprint = resolvePluginMetadataControlPlaneFingerprint(params.config, {
env,
index: snapshot.index,
policyHash: requestedPolicyHash,
workspaceDir: requestedWorkspaceDir
});
if (!(candidate.configFingerprint === requestedConfigFingerprint || snapshot.configFingerprint === requestedConfigFingerprint || Boolean(candidate.compatibleConfigFingerprints?.includes(requestedConfigFingerprint)))) return;
}
if (params.requireDefaultDiscoveryContext === true && options.scopedOwnerContext !== true && candidate.defaultDiscoveryCompatible !== true) return;
return snapshot;
}
function isCurrentPluginMetadataSnapshotRuntimeGeneration(snapshot) {
const gatewaySnapshot = getGatewayPluginMetadataSnapshot();
if (gatewaySnapshot && gatewaySnapshot.index === snapshot.index) return true;
for (let scoped = scopedPluginMetadataSnapshot.getStore(); scoped; scoped = scoped.parent) {
if (!isScopedSnapshotInCurrentCache(scoped)) continue;
if (scoped.snapshot?.index === snapshot.index && scoped.immutableRuntimeGeneration === true) return true;
}
return false;
}
function getCurrentPluginMetadataSnapshot(params = {}) {
for (let scoped = scopedPluginMetadataSnapshot.getStore(); scoped; scoped = scoped.parent) {
if (!isScopedSnapshotInCurrentCache(scoped)) continue;
const compatibleScoped = resolveCompatiblePluginMetadataSnapshot(scoped, params, { scopedOwnerContext: true });
if (compatibleScoped) return compatibleScoped;
}
const scopedCache = getScopedPluginCache();
if (scopedCache && scopedCache !== getProcessPluginCache()) return;
const { snapshot, owner, configFingerprint, envFingerprint, defaultDiscoveryCompatible, compatiblePolicyHashes, compatibleConfigFingerprints } = getCurrentPluginMetadataSnapshotState();
return resolveCompatiblePluginMetadataSnapshot({
snapshot,
configFingerprint,
envFingerprint,
defaultDiscoveryCompatible,
compatiblePolicyHashes,
compatibleConfigFingerprints,
hasConfigIdentity: (config) => currentPluginMetadataConfigIdentityCache.has(config),
immutableRuntimeGeneration: owner === "gateway"
}, params);
}
registerPluginMetadataSnapshotReaders({
adoptCurrentPluginMetadataSnapshotIfAbsent,
getCurrentPluginMetadataSnapshot
});
//#endregion
export { setGatewayPluginMetadataSnapshot as a, hasExplicitPluginIdScope as c, serializePluginIdScope as d, resolvePluginMetadataEnvFingerprint as f, resolvePluginDiscoveryContext as h, isCurrentPluginMetadataSnapshotRuntimeGeneration as i, hasNonEmptyPluginIdScope as l, resolvePluginControlPlaneFingerprint as m, getCurrentPluginMetadataSnapshot as n, withPluginMetadataSnapshotScope as o, fingerprintPluginDiscoveryContext as p, installTemporaryCurrentPluginMetadataSnapshot as r, createPluginIdScopeSet as s, adoptCurrentPluginMetadataSnapshotIfAbsent as t, normalizePluginIdScope as u };